Rails 1.1.4 Runs Unmodified in JRuby

Rails 1.1.4 was released on Friday to very little fanfare. It was basically a fixit release for routing logic that broke in the 1.1.3 release (which broke while fixing a security issue in 1.1.2, etc). However, there's a less visible but vastly more interesting fix (for JRubyists) also included in 1.1.4.

Esoterica

Rails pre-1.1.4 used a peculiar block syntax to handle simple array and hash assignment:

options = {} # a hash
...
some_object.some_method { |options[:key]| }

Which basically boils down to this:

some_object.some_method { |v| options[:key] = v }

The former is certainly terse, but it takes a little head-twisting to follow what's going on. Inifinitely more serious: it doesn't work in JRuby.

Anguish

I don't know when this syntax became valid or if it's always been valid, but it is seldom used. We had not seen it anywhere except in Rails, and there it's only used in a few top-level scripts for gathering command-line options. The level of effort to implement this missing functionality in JRuby is nontrivial:
  • there are parser changes necessary to treat the block arg as an assignment to a hash/array, which is a Call instead of a DVar (dynamic var)
  • there are interpreter changes to allow Call nodes to appear in block arg lists
Salvation

Naturally, we wanted to avoid adding this functionality if possible, so I emailed the ruby-core mailing list to ask the man himself, matz, whether this was an accepted standard. His response was music to my ears:
FYI, in the future, block parameters will be restricted to local variables only, so that I don't recommend using something other than local variables for the parameters.
Redemption

Being the rabble-rouser that I am, and armed with matz's Word, I contacted the Rails team about "fixing" this unusual block syntax. Naturally, we wanted it fixed because it was going away, and not just because we're lazy. A bug was created, patches were assembled, and finally, in 1.1.4, this syntax has been fixed.

Enlightenment

So what does this mean for JRuby? Until 1.1.4 was release, we had planned to include our own patch for this syntax, to allow Rails to work correctly. You would have had to patch Rails after installing, or none of the standard Rails scripts would run. Now, with the release of 1.1.4, the following will all work out-of-the-box with JRuby 0.9.0 (currently in RC status):

gem install rails --include-dependencies
# and use --no-rdoc for now...it's too slow
rails ~/myapp
# might need to tweak the rails script a bit to fix the shebang, or just call "jruby path/to/rails"
cd ~/myapp
jruby script/generate controller MyTest hello
jruby script/server webrick
# specify webrick explicitly; Rails uses platform-dependent tricks otherwise

And suddenly, you have http://localhost:3000/mytest/hello running JRuby on Rails.

We'll have a much better HOWTO packed into the 090 release, and I'll certainly be blogging on various aspects of JRuby on Rails over the next week or two. Keep in mind that we don't officially "support" Rails just yet; there's more work to do. We are, however, another leap beyond the JavaOne demo, and at this rate things are looking very good for an end-of-Summer JRuby 1.0.
Written on July 1, 2006