Ruby One Niner
All my server’s Ruby applications, most notably my books site, have been running on 1.9.1 for over a month now. During the process of upgrading Ruby I jotted down a few notes on the process I followed, the problems I encountered and the ways in which I solved them. None of this is new information, but hopefully bringing these solutions together will be of use to those with similar setups, or at least to myself in the future.
I installed Ruby 1.9.1 on an Ubuntu 8.04 (LTS) server, which was reasonably simple in and of itself, although the Ruby ecosystem as a whole has clearly not quite caught up to the new VM.
Ruby 1.8.6 is still the default version of Ruby available on the Ubuntu package system, and while there is a version of Ruby 1.9 available, it’s quite out of date. For this reason, I recommend compiling it by hand from the source code provided on the Ruby website. This has the additional benefit of making upgrading your version of Ruby independent of the Ubuntu packaging hierarchy, which can be somewhat slow to update theirs.
Uninstalling Ruby 1.8.6—assuming it was installed with
aptitude—is extremely simple:
sudo aptitude remove ruby1.8
The package manager will pick up on the fact that
irb depend on Ruby, and uninstall them as well as
libreadline-ruby1.8 which will be unused when
ruby1.8 is gone.
If you’re following these instructions, make sure you use the latest stable version from the Ruby site, not the one I list here. Given that newer versions are likely to fix bugs and security vulnerabilities, this is extremely important. Blindly copying and pasting shell commands is a sure-fire way to create problems for yourself.
cd /usr/local/src/ sudo curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz sudo tar xzvf ruby-1.9.1-p243.tar.gz cd ruby-1.9.1-p243/ sudo ./configure sudo make sudo make install
The RubyGems packaging system is built into Ruby 1.9, but quite a few gems are not yet compatible with the new VM. There are lots of helpful notes in this blog post, although thankfully not all of them still apply.
Is it Ruby 1.9? generally gives one a good sense of whether just running
gem install foo will work, but is often lacking when it doesn’t. Some research will likely be required if you have a lot of gems.
Some gems just worked
sudo gem install hpricot \ rake \ rack \ rails \ will_paginate \ rdiscount \ fastthread \ passenger
Getting Mongrel to even run was ludicrously complicated. Here are the steps I followed to do so, but before I list them I should note that I don’t think that this is generally worth doing, unless for some reason you can’t possibly switch to an alternative web server such as Passenger.
The changes you’ll need to make to the Mongrel source code concern references to the objects of the underlying C implementation: since Ruby 1.9 is based on an entirely new virtual machine, any direct references to MRI objects have to be changed to instead refer to YARV ones.
ext/http11/http11.cfile to replace references to
sudo ruby setup.rb && sudo make && sudo make install
- Copy the
mongrel.gemspecfile to your RubyGems specifications directory as
Obviously those changes won’t work on Ruby < 1.9. Ryan Bigg has a 1.9-compatible version, although I haven’t tried it personally.
While I did get Mongrel working, it didn’t play nicely with Rails 2.3.2 at all, so in the end I just dropped it and installed Passenger instead, which is much better in this regard, and a lot lower-maintenance. After removing Mongrel I cleaned up the following:
- Config files in
- A symlink to one of the gem files in
/etc/init.d/to restart the cluster if the server rebooted
- A load of
mod_proxy_balancercruft in my Apache configs
Coda Hale’s grown up server was a great hack, but its time is past. Slicehost have good articles on installing Passenger and using it to serve your application, but it’s basically very straightforward.
The MySQL gem on RubyForge is outdated and not completely compatible with Ruby 1.9. The updated gem has to be built by hand, which is a fairly uncomplicated process.
Most of my application code just worked. The only real changes I had to deal with were those concerning the new
String class, but these are well documented and shouldn’t be a surprise to anyone upgrading an application or library to work with 1.9. If in future I run across any other issues, I’ll add them in a supplementary section below.
The new String class
James Edward Gray II has written some very helpful articles on Ruby 1.9’s new
String class and default encodings. They proved invaluable when trying to track down bugs in code written for Ruby 1.8.6 (most of the fruits of my labours in this regard are visible in URLify).
Backwards-incompatible Tempfile changes
After upgrading to Ruby 1.9.1-p243, Books on Extralogical died, with Passenger reporting an
IOError. Apparently a change was made to
Tempfile#unlink to fix some issues with the library on Windows, resulting in a behaviour change that broke programs on *nix systems. I edited the library file and reverted the change, which fixed the application. Hopefully a future version of Ruby will revert this change, or it will be fixed at the library level in Rack. Here’s the path to the file in question on my system:
Update, 26th August 2009
This behaviour has been reverted for the Ruby 1.9 development branch, and the fix will be backported to the 1.9.1 branch. Many thanks to Hongli Lai for pursuing this.
Update, 7th January 2009
Having switched to Gemcutter as my primary gem source, I’ve removed the GitHub gem source details from the article.
In the end, only two things caused me any trouble: installing Mongrel, and installing MySQL. The latter was relatively painless once I found the right version of the library; I really don’t know why the newer version isn’t available on RubyForge. The former was a complete pain, and my advice is to scrap any Mongrel-based setup and install Passenger from the get-go—it’ll be quicker than trying to hack your old setup back together. Now that Passenger is available for nginx as well as Apache, the case is thoroughly compelling.
Last updated 7th Jan 2010