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 therender
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 ofredirect_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 atext/plain
response. Userender :plain
instead orrender :html
to display atext/html
page:
render plain: 'My text'
The
respond_to
andrespond_with
methods have been extracted to the responders gem, so be sure to include it in the Gemfile if you use those methods.XML serialization has been extracted to a separate activemodel-serializers-xml gem as well.
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 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.