Upgrading Rails from 3.0 to 3.1: What You Need to Know

Published  June 25th, 2012

We upgraded the thredUP app from Rails 3.0 to Rails 3.1 this past week. On the day we deployed the upgrade, our test suite was green and everything looked solid locally and on our staging server, but out of sheer paranoia I decided to take one of our front-end servers off of the load balancer and deploy to it so I could poke around on the Rails production environment....and then a bit of chaos ensued.

There are some aspects of a production environment that can't be replicated in your test suite and can't be invoked locally. A good example of this is SSL. Did you know that `ssl_required` was deprecated in Rails 3.1? I didn't (here's the solution btw). Then there are production-only gems to worry about (ex: monitoring services). New Relic's gem required a bump for Rails 3.1. And by required a bump, I mean the gem caused the entire app to crash with a cryptic error message. Fun!

You're probably thinking that this upgrade lacked preparation. Quite the contrary. Before I started the upgrade, I read guide after guide about upgrading to Rails 3.1. Because we wanted to upgrade in phases, I wasn't interested in the asset pipeline requirements, but it seemed as though that was the only thing every guide was focusing on. What the guides weren't focusing on were all the gems that would have to bumped (and their dependencies) and what the ramifications of those bumps would be. ActiveRecord, Cucumber, and PayPalNVP were a couple gems in particular that had noticeable changes that deserved some love in the upgrade guides. So that's what this post is, some love for the not-so-obvious deprecations that should give you clearer expectations of what you'll be running into when upgrading to Rails 3.1.

Active Record

Condition hash syntax is on it's way out. It's been fully deprecated from named scopes and the `find()` method.

Another big gotcha is 'include_root_in_json' being defaulted to false for every model now. Here's the difference:

Small difference between the two, but if all your JSON responses previously had the root included and you have external apps (iPhone, Android, etc.) relying on your app's internal RESTful API (like we do), then it's a significant difference as it's possible all those API endpoints will have to changed or the apps will break. So how to change this? Below I'll demonstrate how to set an app-wide default and then how to override the setting in individual models.

Gem Bumps

Almost every Rails app relies on a myriad of gems. Including our development and test environments, thredUP uses over 50 external gems and a handful of our own private gems we've created over time. When we upgraded from Rails 3.0 to Rails 3.1, there were some notable gems that required version bumps.

There are some big boys in there (ex: mysql2 is our MySQL adapter). If you use any of the above in your app, which I'm betting you do, make sure to take note of their version bumps

PayPalNVP

If you use the PayPal NVP gem, expect to make some changes. The biggest for us was that the PayPal NVP API requires all authentication upon object instantiation. Example:

If you do full 3rd-party API mocking in your test coverage, you could see how this change would be problematic.

Lastly, make sure to read the Rails 3.1 release notes or Ryan Bate's gist of 3.1 RC4 changes. That's where some of the standard Rails-only deprecations will be. The biggest one to note - all forms (or any Rails view helper that results in HTML being outputted into the source) requires a `=` instead of `-`. It's a simple change, but if you use a hyphen on accident, nothing is outputted to source and it can be quite confusing to debug since no errors will occur and nothing is in the HTML.

If you came across any unique errors when you upgraded your app to Rails 3.1, please mention them below in the comments and I'll update the post afterwards to include them.