Moving to Ruby 1.9.1

Ruby 1.9.1 was released more than a year ago, but the migration to it has been slow. Looking forward to using the new Fiber class(1, 2), sexier functional syntax, and, of course, enjoying the speed, I decided to move a Rails app that I had started recently, to 1.9.1.

Here are a few tips:

1) Before you start, consider using Ruby Version Manager to manage your Rubies and gems. RVM allows to quickly switch between various Ruby implementations (including such exotic implementations as MagLev), keeping a separate gem set for each interpreter. It even allows you to create your own named gem sets (per project, for example), which I find a very cool feature. If you use Mysql, follow the instruction on how to compile the Mysql gem here: http://rvm.beginrescueend.com/integration/databases/

2) If for some reason your Rails app is still running Rails 2.3.4, switch to 2.3.5. Rails 2.3.4 is broken under Ruby 1.9.1.

3) After you’ve compiled your Ruby 1.9.1, you should install test-unit, otherwise your Rails app will fail with the error

1
   superclass mismatch for class TestCase (TypeError)

The explanation is that Ruby 1.9.x bundles library minitest instead of Test::Unit. The test-unit gem contains the missing Test::Unit library.

4) As of today, February 28, 2010, running

1
   gem install mongrel

will fail for Ruby 1.9.1 (on OS X Snow Leopard). Clean the gem and build it from another source:

1
   gem clean mongrel && gem install mongrel --source http://gems.rubyinstaller.org

5) James Gray has written an awesome series of articles about strings and encodings in Ruby 1.9.x, and reading them is a must. The problem is that many Ruby libraries do not deal with string encodings under 1.9.x correctly, and offender number one is the Mysql driver. The discussion of the problem can be found here. The solution that worked best for me is monkey-patching the Mysql driver.

Of course, if you store only ASCII in your DB, this is not a problem at all.

6) String#new completely ignores the encoding of the source file, unlike string literals:

1
2
3
  # encoding: UTF-8
  puts         "".encoding.name #=> "UTF-8"
  puts String.new.encoding.name #=> "ASCII-8BIT"

7) The default CSV library is a version of FasterCSV, but it has been renamed to CSV.

8) Remember that Array#to_s and Hash#to_s behave just like #inspect in Ruby 1.8:

1
2
3
4
5
   # ruby-1.9.1
   [1,2,3,'hello'].to_s #=> "[1, 2, 3, \"hello\"]"

   # ruby-1.8.7
   [1,2,3,'hello'].to_s #=> "123hello"

So I had to change code like this:

1
2
3
4
5
6
7
  content_tag :ol do
    examples.collect do |example|
      content_tag :li do
        link_to(example[1], example[0])
      end
    end
  end

to

1
2
3
4
5
6
7
  content_tag :ol do
    examples.collect do |example|
      content_tag :li do
        link_to(example[1], example[0])
      end
    end.join('')
  end

Well, if you ask me whether I have completely switched to 1.9.1, no, I haven’t. I continue to develop the application so that it can be run under both 1.8.7 and 1.9.1, and on our development server the app is deployed with Ruby 1.8.7. For now. But I am full of hope :)