Spiking on a Rails 3 upgrade

Rails 3 is now beta and the core team is asking people to try it out and report issues back. We decided to do a small spike to get some experience with the upgrade process and see if we could help identify any problems. The application we worked on was our own Pivotal Pulse CI aggregation display (which you can see in action).

Here’s a quick overview of the steps we went through:

Install Ruby 1.8.7 using RVM

Install Rails beta gems

Upgrade the app using the rails_upgrade plugin

Tweak things a lot

Drop incompatible dependencies

Profit!

The first thing we had to do was install RVM. Our development machines are standardized on Ruby 1.8.6 — which we wanted to keep, of course — but Rails 3 requires Ruby 1.8.7. We installed patchlevel 174 after finding that higher patchlevels are not stable with RVM.

$ rvm install 1.8.7-p174

We also found it useful to set 1.8.7 as the default.

$ rvm use 1.8.7-p174 --default

That will also set the ruby that TextMate uses (but not RubyMine). If you don’t want to set 1.8.7 as the default, you can manually set the version of Ruby that TextMate uses by specifying the TM_RUBY shell variable. (Tips on how to manage Ruby VM preference in RubyMine appreciated.)

With Ruby 1.8.7 set up, it’s time to install Rails. You need to install from gems, but because it’s a pre-release gem, there are a few extra steps. Here’s what it took on our side:

The first line installs the Rails 3 dependencies that are not, themselves, pre-release gems. RubyGems 1.3.5 has a bug that it won’t install non-pre-release gem dependencies of a pre-release gem. This is fixed in 1.3.6, we hear, but that release has other problems. The second line installs the Rails 3 pre-release gem. The third line fixes a “can’t find executable rails” error, and the fourth line installs the right verison of rack-mount — the current version, 0.5.1, seems to break things.

At this point, you should test your installation by generating and running a new app.

But what we’re really interested in is an upgrade. Step 1 is the rails_upgrade plugin. The Pulse app was managing gems using geminstaller instead of Rails config.gem feature, so we added our gems to the bundler Gemfile by hand instead of using the upgrader task.

An interesting change in Rails 3 is that config/environment.rb has faded into obscurity. Init code that was located within the initialize block should be moved into config/application.rb. Any other code should be moved into initializer files in the config/initializers/ directory. Be careful with scoping of globals; you may need to add some ::s to the front of your constants to get them to work right.

The app needed a few other minor tweaks to get running:

route conversion in the rails_upgrade plugin didn’t retain all the options on the singleton resource definitions.map.resource :login, :controller => "sessions" converted automatically to just resource :login

rails server failed because there was no tmp/pids directory; once we created it, it started right up.

output is now escaped by default in views, so in one place we needed to add raw to get the output markup interpreted.<%= historical_status_list(project) %> # => <%= raw historical_status_list(project) %>

We had a few dependencies that flat-out didn’t work; the most important of these were rspec and rspec-rails. The Pulse tests are all rspec, and while we were able to get them to run by installing Mutwin Kraus’ modified version of rspec-rails as a plugin, they didn’t come anywhere close to passing. This may be due to our use of foxy fixtures – calls such as projects(:project_name) failed, as did references to fixture names in the foreign key fields in fixture yaml files.

Once we finished all the tweaks, we ran rails server, and the application loaded and behaved normally (just not on the first attempt, heh). Pulse is a small enough project that we can say with at least some confidence that the app still works, even though the tests are red. It does feel a little dirty to check that code in though — even to a branch.

Not sure if this was a quirk of my setup or not (it’s been rather quirky lately), but I had to add

gem install sqlite3-ruby

to the process to get the server to fire up. I’ve been running SQLite on other apps, and it’s possible I munged things up trying to upgrade to Rails 3 (I hadn’t found this tutorial yet)(thank you for writing this up!).