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.