Why Rails 3 Will Require Ruby 1.8.7

September 14, 2009

This past weekend I attended the Windy City Rails conference. It was in a great location in the heart of downtown Chicago and seemed to have a pretty good turn out. There were many great talks but this blog post will be focusing on a specific talk, and more precisely, part of a talk. Yehuda Katz gave a talk on the status of Rails 3. One of the things that he mentioned, which you may have already heard, is that Rails 3 will require Ruby 1.8.7 or higher, dropping support for Ruby 1.8.6. He also mentioned why they are doing this and I found the reason to be interesting. It's not that the Rails core team wants to try to take advantage of any specific new features, it's that Ruby 1.8.6 has a bug which has been fixed in 1.8.7.

To see the bug in action, I recommend that you install Ruby Version Manager (rvm). Once you have installed rvm, install Ruby 1.8.6 and Ruby 1.8.7.

The bug is that in Ruby 1.8.6, the hash method for Hash doesn't generate the same hash code for different hashes with the same values:

$ rvm use 1.8.6
$ irb
ruby-1.8.6-p383 > {:x => 1}.hash
 => 1313270 
ruby-1.8.6-p383 > {:x => 1}.hash
 => 1307060 
ruby-1.8.6-p383 > {:x => 1}.hash
 => 1296440 
ruby-1.8.6-p383 > {:x => 1} == {:x => 1}
 => true
ruby-1.8.6-p383 > h = {{:x => 1} => "foo"}
 => {{:x=>1}=>"foo"} 
ruby-1.8.6-p383 > h[{:x => 1}]
 => nil

So despite the fact that two hashes have the same values and are equal, you can't use a hash as a key in a hash, because that depends on the hash codes of the values being equal, which they aren't. This is fixed in Ruby 1.8.7:

$ rvm use 1.8.7
$ irb
ruby-1.8.7-p174 > {:x => 1}.hash
 => 327875 
ruby-1.8.7-p174 > {:x => 1}.hash
 => 327875 
ruby-1.8.7-p174 > {:x => 1}.hash
 => 327875 
ruby-1.8.7-p174 > {:x => 1} == {:x => 1}
 => true 
ruby-1.8.7-p174 > h = {{:x => 1} => "foo"}
 => {{:x=>1}=>"foo"} 
ruby-1.8.7-p174 > h[{:x => 1}]
 => "foo" 

This is important because you could use a hash cache calls to a method that expects a hash, but only if you can use a hash as the key. This is one of the main reasons Rails 3 is going to require 1.8.7. They could make it worth for both 1.8.6 and 1.8.7 and higher, but why? It simplifies things to just require that you upgrade to Ruby 1.8.7 to use Rails 3. If you are using 1.8.6, this is probably a gotcha that you should be aware of.

Posted in Technology | Tags Ruby, Rails

Comments Disabled