Large rails upgrade


How to upgrade to Rails 5

Image 100x100 1071893

Rails 5 has a ton of new features. It addresses almost 500 issues and pull-requests dealing with performance, security and new features. I'm going to list step by step what you will need to migrate from Rails 4.2 to Rails 5.0.

How to upgrade from Rails 4.2 to Rails 5.0

1 - Update ruby

Rails 5 now requires Ruby 2.2.2 or greater. I suggest installing the latest:

  • rbenv
rbenv install 2.3.1
  • rvm
rvm install 2.3.1

2 - Update your gem dependencies to Rails 5

Change Rails version in your Gemfile:

gem 'rails', '>= 5.0.0.rc2', '< 5.1'

Update Rails dependencies:

bundle update rails

You also might need to update some gems. Hopefully you have a nice test suite to rely on; this makes upgrading much smoother. So for each gem you have problems with, go to their documentation and check if they have any guidance for the upgrade.

3 - Update Rails binaries and configurations

Run the following for updating in a interactive mode your files in bin/ and /config:

rails app:update

4 - Generate the db/schema.rb file again

There are changes to the db/schema.rb file. For instance, Rails moved foreign and unique indexes to inside the create_table methods. You don't even need to have a pending migration to generate a new schema.

rails db:migrate

5 - Application classes

Rails 5 has new application classes that you should have and inherit from, the same way as ApplicationController or ApplicationHelper:

  • ApplicationRecord
  • ApplicationMailer
  • ApplicationJob

5.1 - ApplicationRecord

Create your ApplicationRecord:

# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

Change your models to inherit from your new ApplicationRecord:

# app/models/car.rb
class Car < ApplicationRecord
  belongs_to :person

5.2 - ApplicationMailer

Create your ApplicationMailer:

# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  default from: ''
  layout 'mailer'

At this point you may not have your mailer layout. Create one if not:

# app/views/layouts/mailer.html.erb
<!DOCTYPE html>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style>/* Email styles need to be inline */</style>
  <body><%= yield %></body>
# app/views/layouts/mailer.text.erb
<%= yield %>

Then change your mailers to inherit from your new ApplicationMailer.

5.3 - ApplicationJob

Create your ApplicationJob:

# app/jobs/application_job.rb
class ApplicationJob < ActiveJob::Base

Change your jobs to inherit from your new ApplicationJob.

6 - Validation changes on Belongs To relations

Rails 5 has changed the belongs_to relation to require presence by default. Check the PR

So now required: true is deprecated:

belongs_to :company, required: true # deprecated => `required: true`

You should create an initializer to explicitly configure the new behavior for the app:

Rails.application.config.active_record.belongs_to_required_by_default = true

And for every belongs_to relation that is not required, just add optional: true.

belongs_to :company, optional: true

7 - Halt callback chain - throw(:abort)

Active Record or Active Model callbacks no longer halt when returning false. Check the PR

You should create another initializer to explicitly configure this:

# config/initializers/callback_terminator.rb
ActiveSupport.halt_callback_chains_on_return_false = false

So now for every callback you need to halt the transaction you need to throw(:abort) explicitly:

class Person < ApplicationRecord
  before_create do
    throw(:abort) if you_need_to_halt

8 - Parameters does not inherit from Hash anymore

Rails 5 now logs some deprecation warnings for some Hash related methods on ActionController::Parameters. Check the PR

The warnings are like this:

=> (byebug) params.permit(:page, :per).reverse_merge(page: 1, per: 10)
# DEPRECATION WARNING: Method reverse_merge is deprecated
#   and will be removed in Rails 5.1,
#   as `ActionController::Parameters` no longer inherits from hash.
#   Using this deprecated behavior exposes potential security problems.
#   If you continue to use this method you may be creating a security vulnerability in your app that can be exploited.
#   Instead, consider using one of these documented methods which are not deprecated:
# (called from index at (byebug):1)
{"page"=>"5", "per"=>"25"}

9 - Test http request methods

ActionController::TestCase has changed, so on your controller tests or request tests, even if you use rspec-rails. Check the PR

You may see warnings like this:

ActionController::TestCase HTTP request methods
  will accept only keyword arguments in future Rails versions.
  get :show, params: { id: 1 }, session: { user_id: 1 }
  process :update, method: :post, params: { id: 1 }

The idea here is to use keyword arguments over positional arguments. This is a simple code change.

So if you had this in you tests:

get :show, id: 1

You'll need to change to:

get :show, params: { id: 1 }

The keyword arguments accepted are: params, session, flash, method, body and xhr.


The Rails community has been hard at work improving the Rails framework over the last few years. In fact after almost 12 years Rails has shown to be an exceptionally productive and stable framework. This was a major upgrade and had only a few breaking changes. Great deprecation notices will make the upgrade completely painless.


Upgrading Ruby On Rails Guide

More posts about rails Development Ruby