Upgrade Rails from 4.1 to 4.2

Upgrade Rails from 4.1 to 4.2

This article is part of our Upgrade Rails series. To see more of them, click here opens a new window .

This article will cover the most important aspects that you need to know to get your Ruby on Rails opens a new window application from version 4.1 opens a new window to 4.2 opens a new window .

  1. Preparations
  2. Ruby version
  3. Gems
  4. Config files (config/)
  5. Application code
  6. ActiveRecord
  7. ActionMailer
  8. Miscellaneous
  9. Next steps

1. Preparations

Before beginning with the upgrade process, we have some recommended preparations:

  • Your Rails app should have the latest patch version opens a new window before you move to the next major/minor version.
  • You should have at least 80% test coverage unless you have a dedicated QA team.
  • Follow a Git flow workflow to actively manage at least two environments: staging and production.
  • Check your Gemfile.lock for incompatibilities by using RailsBump opens a new window .
  • Create a dual boot mechanism, the fastest way to do this is installing the handy gem next_rails opens a new window .

For full details check out our article on How to Prepare Your App for a Rails Upgrade opens a new window .

2. Ruby version

Rails 4.2 requires Ruby 1.9.3 or later, and Ruby 2.0 (or newer) is preferred according to the official upgrade guide opens a new window .

3. Gems

If you’re using RSpec 2 opens a new window , you’ll need to migrate to RSpec 3 opens a new window , since RSpec 2 doesn’t officially support Rails 4.2. To make this process easier, you can update to RSpec 2.99 opens a new window , which will print a bunch of deprecation warnings at the end of the test run, and you’ll need to fix these before updating to RSpec 3. For more information, check out their official upgrade guide opens a new window .

You can also use the awesome Transpec opens a new window to automate the RSpec 2 to 3 upgrade process.

Once you’re on Rails 4.2, you will be able to remove the Timecop opens a new window gem if you’re using it, and replace it with new test helper methods travel, travel_to and travel_back. See: TimeHelpers opens a new window

4. Config files

Rails includes the rails:update task opens a new window . You can use this task as a guideline as explained thoroughly in this post opens a new window .

As an alternative, check out RailsDiff opens a new window , which provides an overview of the changes in a basic Rails app between 4.1.x and 4.2.x (or any other source/target versions).

After upgrading to Rails 4.2 opens a new window for an application that needs to run in development on port 80, I came across an unexpected problem due to a change in Rack opens a new window . Rails now listens on localhost instead of 0.0.0.0. You will run into the same problem in case you need to access your Rails server from a different machine. To work around it, you need to start your server by binding to 0.0.0.0 by using:

rails server -b 0.0.0.0 -p 80

Alternatively, you can try the solution here opens a new window to avoid providing -b 0.0.0.0 when you start the server. If you’re using Foreman opens a new window and run into this problem, you can edit your Procfile’s web entry so that it reads:

web: bundle exec rails s -b 0.0.0.0

5. Application code

a. ActiveRecord

  • ActiveRecord <= 4.2 suppresses exceptions raised in the after_commit and after_rollback callbacks by default. They are rescued and printed on the log, and they don’t propagate. You can opt into raising these exceptions now by adding the following configuration:
config.active_record.raise_in_transactional_callbacks = true

Starting from ActiveRecord 5.0, these exceptions are always raised regardless of this setting, so you should opt into it and update your code accordingly.

See: https://github.com/rails/rails/pull/16537 opens a new window

  • If you pass an object to #find, you will now run into the following deprecation warning:
DEPRECATION WARNING: You are passing an instance of ActiveRecord::Base to `find`.
Please pass the id of the object by calling `.id`.

You will need to change your .find calls to pass an id instead of an object.

Before:

Comment.find(comment)

After:

Comment.find(comment.id)

The same goes for #exists? calls, if you pass an object as a parameter for it, you will need to provide an id instead.

b. ActionMailer

  • deliver and deliver! are deprecated, in favor of deliver_now and deliver_now!.

Before:

NotificationMailer.daily_summary(user).deliver

After:

NotificationMailer.daily_summary(user).deliver_now

6. Miscellaneous

If you’re using these in your controllers, you will need to add:

gem 'responders', '~> 2.0'

to your Gemfile.

  • Rails’ HTML sanitizer was rewritten to use the more secure Loofah opens a new window gem. As a result, your expected sanitized output might be slightly different for some inputs. If you experience problems with it, you can restore the behavior by adding:
gem 'rails-deprecated_sanitizer'

to your Gemfile. It will only be supported for Rails 4.2, so it’s recommended that you do not do this and stick with the new default HTML sanitizer.

7. Next steps

If you successfully followed all of these steps, you should now be running Rails 4.2! Do you have any other useful tips or recommendations? Share them with us in the comments section.

If you’re not on Rails 4.2 yet, we can help! Download our free eBook: The Complete Guide to Upgrade Rails opens a new window .

Get the book