Prepare Your App for Rails 4 and Ruby 1.9

Well, it had to happen some day.

Pour one out for our dearly beloved Ruby 1.8.7. And if you're still using 1.8.7 for your Rails app, pour yourself a cup of coffee—Rails 4.0 will run strictly on Ruby 1.9.

The Rails master branch was moved to 4.0 two months ago, almost 6 years to the date of the announcement of Rails 1.0, and the primary cited reason for doing so is to get everyone using Rails on Ruby 1.9.

It's difficult to remember a time before Ruby 1.8; indeed, Rails grew up with it. Alas, it will be nice to get the Rails community over onto the same, faster release.

As you know, 1.9 is packed with lots to love. The performance improvements alone make it a worthwhile upgrade—its slick YARV interpreter helped Ruby shake off its slow poke stigma. Combined with native threading and fibers, use 1.9 correctly and you'll be able to implement noticeable speed-ups across your applications.

What's more, Ruby 1.9 is resilient to the hashing denial-of-service attack that was recently brought into the limelight.

Convinced it's time to make the move yet? While there's a whole litany of changes between Ruby 1.8 and Ruby 1.9, if you want to bring your code up to snuff these are some of the more common things you'll have to tweak:

Block local variables

Ruby 1.8.7
x = 33
3.times do |y|
  x = 'chop' * y
end
puts x
# => "chopchop"
Ruby 1.9.1
x = 33
3.times do |y;x|
  x = 'chop' * y
end
puts x
# => 33

Hashes are ordered by insertion order

Ruby 1.8.7
{:a => "a", :c => "c", :b => "b"}
# => {:a => "a", :b => "b", :c => "c"}
Ruby 1.9.1
{:a => "a", :c => "c", :b => "b"}
# => {:a => "a", :c => "c", :b => "b"}
Or using new hash syntax
{a: "a", c: "c", b: "b"}
# => {a: "a", c: "c", b: "b"}

Strings are indexable

Ruby 1.8.7
"lemon"[1]
# => "101"
Ruby 1.9.1
"lemon"[1]
# => "e"

{"a","b"} No longer supported

Ruby 1.8.7
{"San Francisco", "California"}
# => {"San Francisco" => "California"}
Ruby 1.9.1
{"San Francisco", "California"}
# => SyntaxError: (irb):1: syntax error, unexpected ',', expecting tASSOC

Array.to_s is to be taken literally

Ruby 1.8.7
[2011, 2012].to_s
# => "20112012"
Ruby 1.9.1
[2011, 2012].to_s
# => "[2011, 2012]"
[2011, 2012].join
# => "20112012"

Multilingualization

Ruby 1.8.7
String is collection of bytes
"해적선".size
# => 9
"해적선".bytesize
# => 9
Ruby 1.9.1
String is collection of encoded characters
"해적선".size
# => 3
"해적선".bytesize
# => 9
"해적선".encoding.name
# => "UTF-8"

In addition to making the appropriate modifications to your existing code, I would highly recommend that you get RVM running on your machine if you don't have it running already. You can use it to quickly toggle between different versions of Ruby as well as different gemsets, which can mitigate some migration pain. Being able to quickly toggle between versions of Ruby can help you pinpoint where unexpected errors are coming from.

Lastly, be sure to perform all of these updates in a separate branch. Should you encounter difficulties, it will be nice to know that a revert is only a command away. If you need any more guidance, check out this post about what's new in Rails 4.

So hop to it! Transitioning from Rails 3 to Rails 4 while simultaneously transitioning versions of Ruby is a task you don't want to face. The older You will appreciate it. Promise.