I recently finished working with Kathryn Aaker on upgrading Eggs, her farm CSA management software, to Rails 3. While there is a lot of good information out there on upgrading from Rails 2 to 3, we did run in to a few tricky snags not covered in the guides.
One such snag happened only once we actually deployed our work to production. We’d loaded the login screen on the Rails 2 version, deployed the new Rails 3 version to Heroku and then reloaded the login screen only to get a 500 error. Crap! We’d already deployed the upgrade to a staging Heroku instance with no problems. What gives?
Viewing the application logs we found:
ActionDispatch::Session::SessionRestoreError (Session contains objects whose class definition isn't available.
Remember to require the classes for all objects kept in the session.
(Original exception: uninitialized constant ActionController::Flash::FlashHash [NameError])
It appears that Rails 3 no longer uses
ActionController::Flash::FlashHash and Eggs uses the flash to display the login message among other things. So users actively using Eggs while we did the upgrade we actually likely to get this error. And they would continue to see this error until their session expired, they restarted their browser or they cleared their cookies.
The next day was a big pickup for Clark Summit Farm and that evening a time when many were finishing up their orders for wonderfully tasty and sustainably raised beef and pork. A minute after doing the deploy Kathryn actually got a call from the CSA manager who was stressing out because she was getting errors. Double crap!
So there were users out there with encrypted session cookies that held serialized Ruby objects that no longer existed in Rails 3. How could we invalidate those session cookies?
The solution ended up beautifully simple – change the secret token stored in
# Your secret key for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
Foobar::Application.config.secret_token = 'ce90ddf2fb1...69bf25'
We just changed one character and redeployed. This forces all old session cookies presented by the browser to fail decryption and be invalidated. The user doesn’t have a session so they have to log in again. That works for us.
So add this to your Rails 3 upgrade checklist:
Change the secret token used to encrypt session cookies so that users who are using your application when you deploy the upgrade don’t get nasty server error pages.