Saturday, January 24, 2009

RSpec's New Implicit Subjects

In case you missed the announcement, RSpec now supports this badassery.

describe Person do
  describe "born 19 years ago" do
    subject { Person.new(:birthdate => 19.years.ago }
    it { should be_eligible_to_vote }
    it { should be_eligible_to_enlist }
    it { should_not be_eligible_to_drink }
  end
end

Monday, January 19, 2009

clj-record: ActiveRecord for Clojure

I've spent a chunk of the last month (and an absurd amount of the last four days) working on clj-record: an ActiveRecord-like library written in the Clojure programming language. (Clojure is a LISP dialect with badass concurrency features for the JVM.) clj-record aims to provide an idiomatic "functional" API for persistence with many of the features we've come to appreciate from ActiveRecord, currently including validation, (somewhat) convenient associations, and (some) callbacks.

(Persistence requires side-effects, so it can't really be functional, but it can be idiomatic and leverage a great deal of power from being written in a functional language.)

Here's what a model definition looks like:

(ns clj-record.test.model.manufacturer
  (:require clj-record.boot))

(clj-record.core/init-model
  (:associations
    (has-many products))
  (:validation
    (:name "empty!" #(not (empty? %)))
    (:founded "must be numeric" #(or (nil? %) (not (re-find #"\D" %))))))

Coming soon:

  • Even more convenient associations
  • Even more callbacks
  • Serialization of data structures as attribute values
  • A fancy query API
  • Other cool stuff

Check it out!

Friday, January 16, 2009

Ack in Project Skipping Rake

Ack in Project is probably the TextMate bundle I use the most (after the Ruby bundle, I suppose, which I constantly use without even thinking about it). If you haven't already, you should install it immediately for very fast project searches (and recursive searches of just the selected directory, which on its own is hugely useful).

What it took me a while to realize, though, is that my project's Rake files weren't being searched. It turns out this is because Ack will by default search every file of a known type and ignore everything else. Ack knows Ruby as .rb, .rhtml, .rjs, .rxml and .erb, but that's all by default. (You can see what extensions are associated with what types from the command line with ack --help types. This assumes you've got ack installed on your path somewhere.)

To teach Ack about new extensions or entirely new types, create an .ackrc file in your home directory and fill it with things like this:

# Add the .rake extension to the existing ruby type.
--type-add
ruby=.rake

# Create a new type for Clojure source files.
--type-set
clojure=.clj

(type-set can also be used to completely replace a built in type definition. Read about this and all sorts of other ack options from the command line with ack --man.)

In addition to getting .ackrc in place, you also have to tell the TextMate bundle that you want to use it. From inside TextMate do an Ack in Project, hit the "Advanced Options" twisty, and check "load defaults from .ackrc." You're all set.

It may have occurred to you that your top-level Rakefile doesn't have an extension. Likewise for the executables in your Rails projects' script directory. And your Capfile.

Damn.

Luckily, Ack knows unix-ey people like dropping extensions from executables and using a shebang line to tell the shell how to run them. So any file with an unrecognized extension (or none at all) will be checked for a shebang line that might qualify it for the perl, ruby, php, python, shell or xml types!

So that takes care of RAILS_ROOT/script/*. As far as Rakefile and Capfile ... well, the shebang line would really be a lie, since they're not executable without the supporting Rake and Capistrano libraries loaded, but the workaround of adding the shebang will get them into your Ack results. I leave it to you to decide whether the lying shebang or excluded files is a lesser evil, and promise to let you know if I find a better way to get Ack to consider them Ruby.

Thanks for reading!

Sunday, January 04, 2009

Show Me Your Meta

I'm working on a presentation on Ruby metaprogramming, and I'd love to have more examples from the outside world. If there's any piece of metaprogramming you've seen in open-source code that you thought was particularly clever, readable, convoluted, or gratuitous, please comment or email with links to the source (or at least a pointer in the general direction).

If you have some non-public-source example you think is interesting, please feel free to email me along with information about how I can use the example (and whether you want "credit" for supplying it).

Thanks!