Onwards to Rails 5: Additions, Changes, and Deprecations

Share this article

Rails 5, a new major release of the popular web framework, is coming soon and, of course, we are looking forward to it. Refer to this article if you want to read on overview of some new features that will be introduced. Today, however, we are going to dig into some technical details, discuss which methods were removed or deprecated, which settings have been changed, and how to migrate your existing Rails 4 application to version 5.

Don’t forget that after the release of Rails 5, all bug fixes will only be introduced for Rails 5.0.x, whereas regular security fixes will be applied to Rails 4.2.x, as stated in the official maintenance policy.

The source code for this app is available at GitHub.

Preparations

The first thing to take into consideration before proceeding is that Rails 5 requires Ruby 2.2.2 or higher, so if you don’t have this version installed, go ahead and download it now.

Before migrating your existing application to Rails 5, I really recommend you having a solid test suite, otherwise the migration process may become much more complex and painful. For this article I will be using a demo application, called MusicalShop, that was introduced in my screencast series RSpec with Rails. This is a very simple Rails 4 app, but it does have automated tests written in RSpec. You can clone the latest version of the app from this branch.

Also it is advised to migrate to the latest patch version of Rails 4 (which is currently 4.2.5.1). Additionally, you may check that the latest possible versions of gems are used in your project by running

$ bundle outdated

Be careful, though, not to introduce any conflicts by explicitly requiring the latest versions for all your gems (especially for dependencies).

Another thing to consider is some gems may not yet be compatible with Rails 5, so be prepared for that. Browse gem’s dependencies and skim through open issues on GitHub to find out whether other developers are facing problems while using the library with Rails 5. Some gems (like Devise, for example) may need to be included directly from the master branch.

Okay, so go ahead and check that the tests are running successfully:

$ rspec .

Don’t forget that, as Edsger Dijkstra said, “testing can never demonstrate the absence of errors in software, only their presence”. But we’ll hope for the best.

The last thing to do is to switch to another branch so that you can always return to an older version if things don’t go as planned:

$ git checkout -b rails5

Migrating

Take a deep breath and modify your Gemfile:

Gemfile

[...]
gem 'rails', '>= 5.0.0.beta3', '< 5.1'
[...]

Currently Rails is in beta, but a release candidate should be published pretty soon.

Run

$ bundle update

You may also run

$ rake rails:update

which creates the new files introduced in Rails 5, as well as, modifies the old ones.

All in all, Rails 5 configuration files are very similar to Rails 4, so chances are that you’ll be able to boot your app right away while seeing some deprecation messages. Some of you may remember that the migration process from Rails 3 to 4 was much more painful.

Still, many deprecated methods were removed, so if you were using any of them, you’ll have to modify the code base accordingly. Let’s discuss the major changes so that you understand which parts of the app will most require your attention.

Controllers

Okay, first of all, let’s observe changes that relate to controllers.

  • The skip_action_callback method is removed completely.

  • The :nothing option for the render method is deprecated.

  • The *_filter methods (before_filter, for example) are still supported, but deprecated and will be removed in Rails 5.1. Use *_action instead.

  • A nice method redirect_back is being introduced in favor of redirect_to :back. It tries to redirect to an HTTP_REFERER or to the provided location, so you may use it inside your methods:

redirect_back root_path
  • render :text is deprecated, as it does not render a text/plain response. Use render :plain instead or render :html to display a text/html page:
render plain: 'My text'

Views

Every form now has its own CSRF token by default. This is to prevent form hijacking when an attacker injects his own form on the page pointing to some malicious website.

Create an initializer file to control this behavior globally:

config/initializers/per_form_csrf_tokens.rb

Rails.application.config.action_controller.per_form_csrf_tokens = true

Or use the following setting inside individual controllers:

self.per_form_csrf_tokens = true

content_tag_for and div_for methods were removed from ActionView and extracted to the recordtaghelper gem.

Models

Rails 5 introduces a new abstract class (meaning, that it cannot be instantiated) called ApplicationRecord and all models inherit from it by default rather than from ActiveRecord::Base. This is done to prevent monkey-patching ActiveRecord::Base directly. So, you can introduce all extensions inside ApplicationRecord. If you want to employ this functionality, create application_record.rb file inside your models directory:

models/application_record.rb

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

Next ensure that all models inherit from this new class, for example:

models/user.rb

class User < ApplicationRecord
  [...]
end

Another addition is related to belongs_to associations: in Rails 5, the associated record must be present by default. The required option is now deprecated and a new optional parameter is being introduced. This means that, by default, Rails validates that the “parent” record is present before saving the object. If you do not wish to employ this behavior for some association, use

belongs_to :some_parent, optional: true

Rails 5 also comes with a activerecordbelongstorequiredbydefault.rb initializer file that controls this behavior for the whole application. You may create it as well:

config/initializers/active_record_belongs_to_required_by_default.rb

Rails.application.config.active_record.belongs_to_required_by_default = true

before_* callbacks that return false inside your models do not halt the callback chain anymore. If you wish to explicitly halt the callback chain, use throw(:abort) instead:

def my_callback
  throw(:abort) if something_bad_happened
end

New Rails 5 apps comes with a callback_terminator.rb initializer file that controls this behavior:

config/inititalizers/callback_terminator.rb

ActiveSupport.halt_callback_chains_on_return_false = false

Also keep in mind that if you are going to use Rails with PostgreSQL, only version 9.1 above is supported.

Cache

Caching management in development was made more convenient. In Rails 4, we used to have the config.action_controller.perform_caching setting that accepts either true or false. In Rails 5, however, the following code snippet is now present:

config/environments/development.rb

[...]
if Rails.root.join('tmp/caching-dev.txt').exist?
  config.action_controller.perform_caching = true
  config.cache_store = :memory_store
  config.public_file_server.headers = {
    'Cache-Control' => 'public, max-age=172800'
  }
else
  config.action_controller.perform_caching = false
  config.cache_store = :null_store
end
[...]

To enable or disable caching, you can run the rake dev:cache command that creates caching-dev.txt file inside the tmp directory.

Routing

Multiple root routes may exist in the same scope now (previously, an error was raised). You can provide constraints and choose which root to use:

root 'blog#show', constraints: ->(req) { some_condition }
root 'pages#show'

The rails routes command now accepts the following options to search for specific routes:

  • -c returns all routes for the specified controller
  • -g returns routes based on the specified pattern

Tests

ActionController::TestCase HTTP request methods like get and post are deprecated. You should use process instead. For example, in my tests I have calls like:

spec/controllers/albums_controller_spec.rb

[...]
get :index
[...]
post :create, album: {title: ''}
[...]

These should be re-written as

spec/controllers/albums_controller_spec.rb

[...]
process :index, method: :get
[...]
process :create, method: :post, params: { album: {title: ''} }
[...]

The assigns and assert_template methods have been extracted to a separate rails-controller-testing gem. Add it into your Gemfile:

Gemfile

[...]
group :test do
  gem 'rails-controller-testing'
end
[...]

If you are using RSpec like me, add the following lines into your rails_helper.rb file as a temporary fix (RSpec does not support Rails 5 officially yet):

spec/rails_helper.rb

[...]
RSpec.configure do |config|
  config.include Rails::Controller::Testing::TestProcess
  config.include Rails::Controller::Testing::TemplateAssertions
  config.include Rails::Controller::Testing::Integration
  [...]
end

Some Other Stuff

Another cool feature of Rails 5 is that all rake commands now live in rails (for example, rake db:migrate becomes rails db:migrate).

ActiveRecord::Base.raise_in_transactional_callbacks setting is deprecated and has no effect. It will be removed without replacement, so you can safely delete it from config/application.rb file.

ActiveJob now inherits from an intermediate ApplicationJob class. Create an application_job.rb file inside the jobs directory:

jobs/application_job.rb

class ApplicationJob < ActiveJob::Base
end

Make sure that your jobs inherit from ApplicationJob.

ActionDispatch::Static accepts custom HTTP headers, so you may specify custom cache-control options.

The last thing to note is that ActionCable does not require Redis, EventMachine, and Celluloid to be present anymore.

Conclusion

So, Rails 5 promises a great set of new features and additions and I really encourage you to give it a try. Also, be sure to browse the complete changelog.

Are you planning to migrate to Rails 5 in the nearest future? How many of your apps are still running Rails 3 (or even Rails 2)? Share your opinion in the comments!

Frequently Asked Questions (FAQs) about Rails 5 Additions, Changes, and Deprecations

What are the major changes in Rails 5 compared to previous versions?

Rails 5 introduced several significant changes to improve the overall performance and user experience. The most notable change is the introduction of Action Cable, a new framework that integrates WebSockets with Rails to provide real-time features. Rails 5 also introduced API mode, which allows developers to create API-only applications more efficiently. Other changes include the replacement of the “rails new” command with “rails new –api” for creating API-only applications, and the deprecation of certain methods and features to streamline the framework.

What is Action Cable in Rails 5 and how does it work?

Action Cable is a new feature in Rails 5 that integrates WebSockets with Rails to provide real-time functionality. It allows for real-time features to be written in Ruby in the same style and form as the rest of your Rails application, while still being able to have real-time features on the client-side with JavaScript. This makes it easier to create chat applications, notifications, and other real-time features.

How does the API mode in Rails 5 improve the development process?

The API mode in Rails 5 allows developers to create API-only applications more efficiently. When you create a new Rails application using the “rails new –api” command, Rails will start up in API mode and only a subset of middleware will be loaded. This means that any middleware that is not required for API-only applications will not be loaded, resulting in a leaner and faster application.

What methods and features have been deprecated in Rails 5?

Rails 5 has deprecated several methods and features to streamline the framework. For example, the “respond_to” and “respond_with” methods in ActionController have been moved to the responders gem. Other deprecated features include certain test runner commands and the “render nothing: true” option in controllers.

What is the responders gem and why was it introduced in Rails 5?

The responders gem was introduced in Rails 5 as a way to handle the “respond_to” and “respond_with” methods that were deprecated from ActionController. This gem provides a set of responders modules to dry up your Rails 5 API and make it more maintainable and clean. It allows developers to continue using these methods without having to rewrite their code.

How does Rails 5 handle test runner commands differently than previous versions?

In Rails 5, certain test runner commands have been deprecated and replaced with new ones. For example, the “rake test” command has been replaced with “rails test”. This change was made to make the test runner more consistent with other Rails commands.

What is the “render nothing: true” option and why was it deprecated in Rails 5?

The “render nothing: true” option in controllers was a way to render an empty response with a 200 OK status code. In Rails 5, this option was deprecated and replaced with “head :ok”. This change was made to make the controller actions more explicit and easier to understand.

How does Rails 5 improve the performance of applications?

Rails 5 introduces several performance improvements. For example, the introduction of API mode allows for leaner and faster applications. Additionally, the integration of WebSockets with Rails through Action Cable allows for real-time features to be implemented more efficiently.

What is the purpose of the “rails new –api” command in Rails 5?

The “rails new –api” command in Rails 5 is used to create API-only applications. When you use this command, Rails will start up in API mode and only a subset of middleware will be loaded. This results in a leaner and faster application, as any middleware that is not required for API-only applications will not be loaded.

How does Rails 5 handle real-time features differently than previous versions?

Rails 5 introduces Action Cable, a new feature that integrates WebSockets with Rails to provide real-time functionality. This allows for real-time features to be written in Ruby in the same style and form as the rest of your Rails application, while still being able to have real-time features on the client-side with JavaScript. This makes it easier to create chat applications, notifications, and other real-time features.

Ilya Bodrov-KrukowskiIlya Bodrov-Krukowski
View Author

Ilya Bodrov is personal IT teacher, a senior engineer working at Campaigner LLC, author and teaching assistant at Sitepoint and lecturer at Moscow Aviations Institute. His primary programming languages are Ruby (with Rails) and JavaScript. He enjoys coding, teaching people and learning new things. Ilya also has some Cisco and Microsoft certificates and was working as a tutor in an educational center for a couple of years. In his free time he tweets, writes posts for his website, participates in OpenSource projects, goes in for sports and plays music.

GlennGRuby on Rails
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week