Install Ruby on Rails (Best Tutorial 2019)


Ruby on Rails

Upgrading to Ruby on Rails 5 Tutorial 2019

Before you touch your Rails application, you must ensure that the version of Ruby you are using is 2.2.2 or above. At the time of writing, the latest version of Ruby is 2.5.0. Since Ruby 2.5 features a number of performance and memory management improvements, you should use it, if possible.


This tutorial explains best ways to install Ruby on Rails 5 on OS X, Linux and Windows 10.  And also explains why we use Rails 5 for an API Application. How you upgrade your Ruby installation depends entirely on the setup of your development environment on your local machine.

If you are using OS X or Linux, then you are likely to be using rbenv, RVM, or chruby.

 so upgrading should be a simple matter of building and switching to the necessary version.


If you are running Windows, RubyInstaller for Windows has installers available for up-to-date versions of Ruby.


Of course, if you intend to upgrade any production applications to Rails 5, you must ensure that your production servers are upgraded to a suitable version of Rails before you deploy your application.


Depending on the version of Rails that your application is currently using, it may not be compatible with Ruby 2.5.0, so you must take that into account when upgrading and planning your deployment.


You should specify the Ruby version in your application’s Gemfile. Do this by placing the ruby directive in your Gemfile. For example:

ruby '2.5.0'

While this is not a requirement, it is good practice because it ensures that all the developers working on your project and your test and deployed versions are running on the same release of Ruby.


Upgrading the Rails Gem

Once you’re happy with your application’s test coverage and you have ensured that you have the up-to-date version of Ruby, it’s time to switch your application to Rails 5.


Before you move to Rails 5, you should ensure that your application works fine on the most recent version of Rails 4.2 in order to ensure that you spot any deprecation warnings or have other issues with your application that aren’t a result of the move to Rails 5.


Now change the specified version of Rails in your Gemfile to 5.0.0:

gem 'rails', '5.0.0'


Then run the bundle update command, specifying to update the Rails gem.

$ bundle update rails


This installs the latest Rails gem, along with all the necessary dependencies. If you look at the differences in your Gemfile.lock before and after the bundle update,

you see that all of the Rails-related gems (such as activerecord, actionpack, and actionview) have been upgraded.

You also notice a new addition, actioncable.


The rack gem has been updated to the latest version of the Rack 2 gem. Rails 5 is not compatible with older versions of Rack.


Rails Update

You should now run the Rails update command to update the Rails support files, such as the default configuration files and initializers.


To initiate this, enter the following command:

$ rails rails:update

This command checks all the relevant files; it skips identical ones, creates new files, and asks for permission to update any conflicting ones.

For example:

conflict config/environments/production.rb

Overwrite /Users/alan/Projects/Sensors/config/environments/production.rb? (enter "h" for help) [Ynaqdh]


Pressing the D key shows the difference between the current version and the version that would replace it. Either use this to update your local file manually, or overwrite your file and then add your edits.


Be sure to take a look at all the files there were added or changed by this process to understand if there are any implications for your application.


Application Record As the Base Class for Active Record Models

By default in Rails 5, when you generate a new model, it is created to inherit from a model called ApplicationRecord.

This is similar to how Rails controllers inherit from ApplicationController. It gives you a place to keep common methods and behaviors for your models.


The model generator checks in your app/models directory; if a file application_ record.RB exists, it uses that as the superclass for the model being generated, rather than ActiveRecord:: Base. Since this is the preferred new behavior for Rails 5, you should create the app/models/application_record.RB file and enter the class.


Listing The New Default ApplicationRecord Base Class

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


You should then update your existing model files to inherit from this. For example, change

class Product < ActiveRecord::Base


class Product < ApplicationRecord

While doing this isn’t mandatory, it is the expected and preferred behavior for Rails 5 applications, so it makes sense to bring your application up to date.


Application Job As the Base Class for ActiveJob Jobs

Similar to ActiveModel classes now having the ApplicationRecord superclass, newly generated ActiveJob jobs inherits from ApplicationJob if the app/jobs/application_job.RB file exists.


To keep in line with this behavior, you should create the app/jobs/application_job.RB file with the class definition in Listing


Listing The New Default ApplicationJob Base Class

class ApplicationJob < ActiveJob::Base end

Then update any existing job classes to inherit from this by changing the superclass. For example, change

class CalculateRatingsJob < ActiveJob::Base


class CalculateRatingsJob < ApplicationJob


While the default ApplicationJob class is empty, you should look at moving any methods or configurations shared by all of your jobs to the superclass.


Upgrade to PostgreSQL 9.1 or Later

If you are using PostgreSQL as the database for your application, you must ensure that you are using PostgreSQL version 9.1 or higher. Previous versions are past their end-of-life date and support for them has been dropped from Rails 5.


Devise Gem

If your application makes use of the popular Devise gem for authentication, you need to change your Gemfile to use the most up-to-date commit from Devise’s page on the GitHub repository. At the time of writing, there is no official versioned release of Device that is compatible with Rails 5; but the required changes have been committed to GitHub.


To do this, edit your Gemfile and change the entry for Device as follows:

gem 'devise', git: ''

You must then perform this:

$ bundle update devise


If you attempt to use an older version of Devise, you encounter the following error:

uninitialized constant ActionController::RackDelegation

The device is a very popular gem, so this is a common problem to encounter when updating an app to Rails 5.


Callback Chain Changes

Rails 5 has slightly changed the behavior of callback chains.

In Rails 5, the preferred method to halt a callback chain is to explicitly call throw(: abort); whereas in previous versions of Rails, you could simply return false from a callback method.


When you upgrade an old application to Rails 5, the application still performs as expected, but you receive deprecation warnings. Once you have brought your application up to date, you can fully enable the new behavior and remove the deprecation warnings by adding an initializer file containing this line:


ActiveSupport.halt_callback_chains_on_return_false = false

New applications created with the Rails 5 application generator already include this config statement.


Running Tests

You should now be ready to run your test suite and start to pick off any necessary gems that require updating, one by one. Remember, with Rails 5, you run your tests with the rails command rather than rake:

$ rails test

You will almost certainly find some deprecation warnings and some incompatible gems. Check the support pages for the gems as most will have been updated to work with Rails 5.


Changes from Rails 4.2

In this blog, I go through the majority of the important changes to Rails, excluding Active Record and the testing framework.


While most of the changes seem small, there are some great refinements of the framework, making your day-to-day development work easier, allowing greater configuration and flexibility, and bringing the framework up to date.

I’ve omitted changes that are simply bug fixes or internal changes that don’t affect application development.


Ruby 2.2 or Higher

If you are upgrading from an earlier version of Rails, or just about to start a new Rails 5 project, the very first thing you need to know is that Rails 5 requires Ruby version 2.2.2 or above.


To check your version of Ruby, just use ruby -v.

$ ruby -v

ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin15]


One of the main reasons for requiring Ruby 2.2 is so that Rails can take advantage of the improvements to the garbage collection. In 2.2 and above, symbols are now garbage collected, resulting in improvements in memory management and lower memory usage.


Garbage collecting symbols also prevent denial-of-service attacks that could make your application consume ever-increasing amounts of memory.


Ruby 2.2 also uses an improved system called incremental garbage collection, resulting in a large performance increase.


If you’re interested in learning more about the garbage collector changes.



Also, Rails 5 makes extensive use of keyword arguments to tidy up a lot of code. The keyword arguments feature was introduced in Ruby 2.1.


To take advantage of the new Ruby features, the improved garbage collector, and the speed and security enhancements, the core team decided to drop support for older versions of Ruby.


Ruby 2.5.0 was released in December 2015, and at the time of writing, it is the recommended version of Ruby because it contains a number of performance enhancements.


Rails Commands

In this section, I go through changes to Rails commands.


Rake Tasks

Another change that you’ll quickly come across is the multitude of rake tasks that you use in day-to-day Rails development.

such as db:migrate, assets:precompile, and test—have all been aggregated under the rails command.
So, for instance,
$ rake db:migrate
simply becomes
$ rails db:migrate


The thinking behind this is that it’s confusing to have a separation between the two— using a rake for some things and rails for other tasks. Using rails for everything means you never have to worry about which to use.

To get full details of all available tasks, use the following:

$ rails --help


Rails Restart

A new command has been added to the application admin tasks: rails restart. This command is simply a convenience method that touches the tmp/restart.txt file within your application, indicating to Spring (the process that starts and controls the Rails development process) that the application should be restarted.

$ rails restart


Rails Initializers

The rails initializers command is newly added. It lists the complete set of initializers that are run (and the order that they are run in) when your application is started.

$ rails initializers


The update Command

A new script has been added to the bin directory of a generated application: an update. You can use this script to automatically update your development environment, which is useful after you have pulled someone else’s changes from your source control.


The script performs the following tasks:

  • Ensures that the bundler gem is installed
  • Runs bundle install
  • Performs any database migrations with db: migrate
  • Clears your application’s log files and temp directory
  • Restarts your application
$ bin/update
Installing dependencies
The Gemfile's dependencies are satisfied
Updating database
Removing old logs and tempfiles
Restarting application server


Development Cache Toggle

A small addition to the available rake commands is the ability to quickly enable and disable the cache for development mode. Obviously, this was possible before, but it required editing the config file and restarting the server. Having it available as a rails command just makes it more convenient.

$ rails dev:cache


Development mode is now being cached.

This can quickly be turned off again by repeating the following command: $ rails dev:cache


Development mode is no longer being cached.

You can also start your development server with caching enabled or disabled, which overrides the settings in the environment file by using the options --dev-caching or --no-dev-caching.

$ rails server —-dev-caching


Beyond Ludicrous Speed

The Rails 5 release includes a pull request by Richard Schneeman that has the tantalizing title “Beyond Ludicrous Speed.”

This PR is the result of the extensive investigation and benchmarking work by Schneeman to make a number of seemingly minor changes to the Rails internals, such as removing duplicated hashes, freezing strings, and tidying arrays. By doing this, he has dramatically reduced the number of allocated objects, and hence memory used per request, leading to a speed increase of 11.9%.


I highly recommend taking at a look at the pull request at Build software better, together rails/rails/pull/21057 to understand the changes and to see how small changes can have large effects when optimizing your code.


The best part of this feature is that it requires no change on your part; nothing has changed externally—you can just enjoy the performance increase!


Asset Serving

You are likely aware that Rails has a built-in server for serving public assets such as JavaScript, CSS, and image files.


In most applications, you’ll likely use the static asset server in development and test mode, but make use of your web server’s assets serving in production mode. However, if you host a Rails application on Heroku, your assets are served directly by Rails.


As part of the Rails 5 upgrade, the built-in asset server had an overhaul. Previously, you had very little control over how static assets were served. Apart from enabling and disabling the server, the only setting you could change was the cache-control header. This means that you are unable to set additional headers, such as Expires.


Public File Server

The previous config settings—static_cache_control and server_static_files—have been deprecated as of Rails 5; they will be completely removed in Rails 5.1.


In their place is the new public_file_server configuration. The two settings are now set by the enabled and headers attributes of the public_file_server config setting, where the headers attribute allows you to set any headers, not just cache-control.

To update an older application, make the following changes.

config.serve_static_files = true
config.public_file_server.enabled = true
And the cache_control is just one of the file server headers.
config.static_cache_control = 'public, max-age=172800'
config.public_file_server.headers = { 'Cache-Control': 'public, max-age=172800'
The following is an example with the Expires header:
config.public_file_server.enabled = true config.public_file_server.headers = {
'Cache-Control': 'public, max-age=172800',
'Expires': "#{1.month.from_now.to_formatted_s(:rfc822)}"
Obviously, this is settable on a per-environment basis in your config/environments/ [environment].rb files; you can set different headers as necessary.



This section covers changes to rendering in Rails 5.

Render from Anywhere

Prior to Rails 5, the render method could only be called from within a controller. At first glance, this appears to be a sensible limitation, since it seems to be where you will always need to render views.


On occasion, however, you may need to render a template; for instance, from within a background job or a script, or when responding on a web socket.


There have been some gems that provide a workaround to this, but Rails 5 allows you to perform a render from anywhere within your application.


To do this, you simply use the render method like this:

ApplicationController.render template: 'orders/index.html.erb'

You can also call the render method of a specific controller. For example:


OrdersController.render :index

It’s likely that when rendering a view template, you will need to assign objects so that the view can be rendered with the necessary data.


When calling render from a controller, you just set variables before calling render, but when calling from outside a controller, you must assign the relevant objects using the assigns option. Also, the usual local's option can be used to pass in local variables. For example:


OrdersController.render :show, locals: { user: current_user }, assigns:

{ order: order }


The actual renderer object is accessible via the renderer method. You can see the environment that the view template is rendered in by calling the defaults method on this renderer:



=> {:http_host=>"Example Domain", :https=>false, :method=>"get", :script_name=>"", :input=>""}
By instantiating a new renderer, you can change the environment that the renderer is performed in. For example:
orders_renderer = 'post', https: true)
=> #<ActionController::Renderer:0x007fc606a09e10 @controller=OrdersController, @defaults={:http_host=>"Example Domain", :https=>false,
:method=>"get", :script_name=>"", :input=>""},
@env={"HTTP_HOST"=>"Example Domain", "HTTPS"=>"on",
"REQUEST_METHOD"=>"POST", "SCRIPT_NAME"=>"", "rack.input"=>""}>
You can subsequently perform render calls on that renderer instance.


Render Nothing Deprecated

The nothing option of the render method has been deprecated; it will be removed in Rails 5.1. If you wish to respond with no body, simply use the head method instead.


So if you are currently responding to any requests with an empty body, say in an API controller, using this:

head :ok

Of course, you can send any HTTP response, such as :created or :not_found with the head command.


HTTP Cache Forever

Action Controller has gained the http_cache_forever method. It allows you to define an HTTP response that has an expiry date 100 years in the future, meaning that the browser should cache it indefinitely. This is useful for pages that rarely change, such as static pages.


By default, the response is private, meaning that proxies do not cache it, but it is cached on the user’s browser. By specifying that the response is public, it is also cached by proxy servers.


The method also allows you to set a version string. By changing this version string, the ETag that is used to check if the cached data requires updating is updated, busting the cache.


The listing shows an example controller where the response to the index method will be cached indefinitely on the user’s browser and any proxies.

Listing Caching a Static Response

class StaticController < ApplicationController def index
http_cache_forever(public: true, version: 'v1') do
render plain: 'hello'


Multiple Root Routes

It is now possible to set multiple root routes in your routes.rb file. This is useful if you need to specify different routes based on constraints.

For example:

root 'blog#show', constraints: ->(req) { Hostname.blog_site?( } root 'home#show'


If the request meets the conditions set by the constraints block, then the first root is used; otherwise, it falls back to the second one.


This was possible in earlier versions of Rails by using a get route, but the change allows you to clarify your intentions and makes it possible to always just use the root_path and root_url helpers and have them respond to different conditions.


Static Index

A new configuration option that allows you to set the file shown as the static index has been added. By default, Rails looks for a file called index.html in the public directory. If you wish to change this, add the setting to your config/application.rb file, as follows:

config.static_index = 'main'


Active Model

This section covers changes in the active model.


Halting the Callback Chain

Previously in Rails, when you had a before callback for a model, if that callback method returned false, then the callback chain would be halted, the save method would return false, and save! would raise a RecordNotSaved exception.


In Rails 5, the preferred method to halt a callback chain is to explicitly call throw(: abort).

If the halt_callback_chains_on_return_false config setting is set to true, then returning false still has the desired effect, but you receive a deprecation warning; otherwise, returning false does not halt the callback chain, to ensure that you update any existing applications.


XML Serializer Removed

Rails 5 has removed ActiveModel::Serializers::Xml, which means that you can no longer perform to_xml on an object.

It was removed simply because it wasn’t used by the majority of Rails applications.

If you still require XML serialization, you can simply install the activemodel-serializers-xml gem to restore this functionality.


The Case Sensitive Option for Confirmation Validator

There is now a new option for the confirmation validator: the ability to make the validation case insensitive. Previously, if you defined a confirmation validation, let’s say on an email address, the email and email_confirmation attributes must be identical, including the case.


By setting case_sensitve: false, you can make this validation case insensitive. For example:

class User << ActiveRecord::Base validates :email, confirmation: { case_sensitive: false } end> user = '', email_confirmation: 'ALAN@ KumaCode')
> user.valid?
=> true
validates_acceptance_of Accepts True


A small change to the validates_acceptance_of validation is that now both 1 and true are accepted as acceptance.


Previously, the validation accepted only 1 as acceptance and it would be returned from an HTML form. You could add an accept: true option if you needed to validate a database column. But now, both values are acceptable, which allows simplification in models using this feature.


Dirty Model Accessor Methods

Two new methods allow you to query the changes to an object after an object has been saved directly for a given attribute. Previously, once an object was saved, changes were only accessible through the previous_changes method, which listed all changed attributes.


To make the API consistent with how the changes before saving are accessible, you can now query [attribute]_previously_changed? and [attribute]_previous_change.

For example:

> = "Alan" => "Alan"
=> true
> user.name_previously_changed? => true
> user.name_previous_change
=> [nil, "Alan"]
Action Mailer

Now let’s look at changes in the action mailer.


Force the SSL Setting Used for Mailer URLs

The Rails config.force_ssl = true configuration setting now automatically sets the mailer configuration options to ensure that any URLs generated by the mailer templates use HTTPS as the protocol. This effectively sets the following option for you:

config.action_mailer.default_url_options = { protocol: 'https' }`


Deliver Later Queue Name

The Active Job queue used to be set to mailers. It is now configurable simply by setting the following config attribute:

config.action_mailer.deliver_later_queue_name = "email_queue"


Templates User Default Locale and Fallbacks

When selecting which mailer template to use, Rails 5 now properly respects the default locale of the application; whereas previously, a template without any locale specified would be used.


Email Template *_path Helpers Deprecated

The *_path helpers have been deprecated in template files. The reason for this is that any links in emails must be an absolute URL, rather than a relative path. Hopefully, *_path helpers were never used in any email templates; but now they’ve been deprecated to ensure that they aren’t!


Remove deliver and deliver! Methods

The delivery and deliver! methods have been removed as of Rails 5. They were deprecated in Rails 4.2, so you should already have switched to using the deliver_later and deliver_now replacements, but it’s worth checking to ensure that the old methods aren’t still in your application.


Class Naming Follows Rails Conventions

When you generate a new mailer using the Rails generator, they are now created following the Rails convention of using a suffix for the type of class—in this case, _mailer.

$ rails g mailer User
create app/mailers/user_mailer.rb
create app/mailers/application_mailer.rb
invoke erb
create app/views/user_mailer
create app/views/layouts/mailer.text.erb
create app/views/layouts/mailer.html.erb
invoke test_unit
create test/mailers/user_mailer_test.rb
create test/mailers/previews/user_mailer_preview.rb



There is one change in internationalization. Pick up New Locales Without Restart. If you have spent time localizing an application, you know that new locale files are only picked up when the Rails server is restarted.


When running in the development environment in Rails 5, I18n.load_path is automatically reloaded, so you don’t need to restart the server to make new locale files available.


Active Job

This section covers changes to Active Job.


Application Job Base Class

In previous versions of Rails, each background job generated simply inherited from ActiveJob:: Base. Until you generated a job class, the app/jobs directory didn’t exist.

In Rails 5, all generated applications include an app/jobs directory that contains an application_job.RB file. All newly generated job classes inherit from this ApplicationJob class.


This follows the same conventions as controllers and mailers using an Application* class as the base class. It allows you to set up application-wide settings and methods. If you are upgrading from a previous version of Rails, you should change your jobs to this style.


Keywords in Process Methods

The Active Job perform method now lets you use keyword arguments. Previously, you were limited to passing only a series of unnamed arguments. If you wanted to use named parameters, you had to pass a hash to the perform_later method. For example:

def perform(hash)
image_id = hash[:image_id]
processing_options = hash[:options)
# do image processing

But Rails 5 allows you to use regular Ruby keyword arguments in your perform_ later method call. For example, a job could be defined as shown in Listing


Listing Active Job using Keyword Arguments

class ImageProcessJob < ApplicationJob queue_as :default
def perform(image_id: image_id, processing_options: options)
# image_id and processing_options are now available!
# do image processing
and called with the following command:


ImageProcessJob.perform_later(image_id:, processing_options: "-s 300x300")


Defaults to Async Queue Adaptor

Previously, Active Job did not have a default queue adaptor setup. Without defining one, Active Job would not allow you to create new jobs until you had configured it properly.


Rails 5 defaults to the: async queue adaptor, which means that when you start a new application, you can develop using background jobs right away, without worrying about configuration first.


The async adaptor uses a concurrent Ruby thread pool to process the jobs asynchronously outside of the main request but within the same system process. This means that it doesn’t require any external dependencies or configuration. However, it is only suitable for development and test environments; you should never use it in production.


Job Priorities

Active Job allows you to place jobs on different queues, which in turn can have different priority levels. For instance, you may have a clean-up job queue that can run at a very low priority, but a mailer queue that runs on a high priority.


Previously, the priority of these queues had to be set manually when configuring your choice of the backend (e.g., Sidekiq, Rescue, or Delayed Job). However, for backends that support it, Rails 5 allows you to override the priority level of the job in the job class. 


Listing Active Job Class Using Queue Priority

class ImageProcessJob < ApplicationJob queue_with_priority 50
def perform(image_id: image_id, processing_options: options)
# do image processing

Note that at the time of writing this is only currently supported by Delayed Job and Que; for other backed Active Jobs, the priority level must be set per queue.


Other Changes

Finally, let’s look at some miscellaneous changes.


Mime Type Constants Deprecated

Up until now, when dealing with MIME types within Rails, it was normal to use constants such as Mime::HTML or Mime::JSON.

As of Rails 5, these constants are deprecated. They are now accessible through accessors like Mime[:html] and Mime[:json].


Since using the Mime[:html] format is valid in older versions of Rails too, you should consider updating older applications and libraries.


Documentation Generating Tasks Removed

The doc: app, doc: rails, and doc: guides documentation generation tasks have all been removed. This is simply because they were rarely used. Developers appear to prefer to use online documentation.


Removing these tasks from the Rails gem means that they no longer need to be maintained. It also means that the entire Rails documentation doesn’t need to be bundled with every download of the Rails gem.

method_source Gem


To aid with debugging, the method_source gem has been included as a dependency. This gem allows you to display the source or comments for any method. When used in conjunction with the development console, this can be very useful.


Even though the gem is installed, to use it, you need to require it:

> require 'method_source' => true

You can then use the source and comment methods on the method, passing the name of the method that you wish to view.


For example, I can view the source of the process method for an instance of my Order class by using method(: process).source.

 puts Order.first.method(:process).source
Order Load (1.0ms) SELECT "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT 1
def process
# Do complicated processing here
=> nil


By using this, you can also view the source and comments on any Rails method, making it a very useful tool for development and debugging.

> puts User.first.orders.method(:load).comment
User Load (1.0ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
# Causes the records to be loaded from the database if they have not
# been loaded already. You can use this if for some reason you need
# to explicitly load some records before actually using them. The
# return value is the relation itself, not the records.
# Post.where(published: true).load # => #<ActiveRecord::Relation> => nil


This also works on dynamically generated methods.

Note There are discussions about adding this functionality into future versions of Ruby. If that happens, it’s highly likely that the method_source gem will be removed and Rails will rely directly on the Ruby feature.


Autoload All Concerns

Rails 4 added the concept of concerns, which provides better support for abstracting reusable code from classes. Previously, Rails only automatically loaded concerns from within the app/controllers/concerns and app/models/concerns directories.


Now, Rails 5 autoloads any concerns from within any subdirectory of the app; so if you create app/mailers/concerns then any files within there are automatically loaded and available to mailers.

div_for and content_tag_for Helpers Removed


The div_for and content_tag view helpers have been removed as of Rails 5. If you still require them, you can restore their functionality by simply adding the record_tag_ helper gem to your application.


Active Record

Active Record is a vital part of the majority of Rails applications, so it’s great to see that it is constantly being refined, optimized, and improved upon. The Rails 4.2 release brought large performance improvements and Rails 5 improves upon this further still.


It goes without saying that many hundreds of small bug fixes and tweaks have been committed to the latest version of Active Record, but in this blog, I concentrate on the biggest and most important changes and additions, and I note any relevant fixes.


The Arel OR Condition

Rails 5 adds a very useful or condition to the Active Record Query Interface, equivalent to using the OR condition in SQL.

Previously, to perform an OR database query, such as

SELECT * FROM users WHERE name='Mary' OR height > 179
you either had to fall back to using SQL directly or use the underlying Arel table information. For example:
t = User.arel_table
results = User.where(t[:name].eq('Mary').or(t[:height].gt(179)))


In Rails 5, you can directly use the or query using the following syntax:

User.where(name: 'Mary').or(User.where('height > ?', 179)) has_secure_token


A small but very useful addition to Rails 5 has _secure_token. Used in a way similar to the ActiveRecord:: Base#has_secure_password method, it specifies that an attribute of your model should be used to store a unique 24-character alphanumeric token.


Tokens such as this are often used in Rails applications for providing token-based API access or allowing one-time access for password reset actions. Since it is such a common use case, it’s very convenient to have it built into Rails.


To add a secure token column to an existing model, you can use the migration generator:

rails g migration add_auth_token_to_users auth_token:token

This creates a migration to add a string column called auth_token and adds a unique index on that column.


Listing Migration to Add a Secure Token to a Model

 style="margin:0;width:960px;height:146px">class AddAuthTokenToUsers < ActiveRecord::Migration def change
add_column :users, :auth_token, :string
add_index :users, :auth_token, unique: true end
You then need to add the has_secure_token statement to the relevant model.
Listing Class with Secure Token Defined
class User < ActiveRecord::Base
has_secure_token :auth_token


The name of the model attribute defaults to token if no name for the column is specified.

The actual token value is generated in a before_create handler, so the value is only available after you have successfully created an item. After that, the value does not subsequently change, as shown here:

$ user =
$ user.auth_token
$ user.auth_token
=> "MsCqa4Ki3z4okKvH7s3F3FD4"

At the time of writing, there is an open issue concerning the fact that some databases (including MySQL) create columns as case insensitive by default.


Since the auth token generated by Rails is a case-sensitive base 58 string, it’s possible that two different keys would be considered the same, even though they have a different case.


If you are using MySQL, you should read the discussion at Build software better, together rails/rails/issues/20133. Make sure that my changing the auth_token column type is taken into account.


[Note: You can free download the complete Office 365 and Office 2019 com setup Guide.]


Multiple Tokens

You can specify multiple token attributes in a model, simply by adding additional has_secure_token statements.


Listing Class with Multiple Secure Tokens

class User < ActiveRecord::Base
has_secure_token :auth_token
has_secure_token :password_reset_token


Regenerating the Token

If you need to regenerate the token (say, for instance, the user wishes to reset the API key), then you can use regenerate_*, specifying the attribute name.


For example, in our earlier examples with the token attribute called auth_token, you would use regenerate_auth_token.


This regenerates a new token and saves the new value in the database. For example:

>$ user.auth_token
=> "MsCqa4Ki3z4okKvH7s3F3FD4"
$ user.regenerate_token
=> "LuSLZLvyEn6YjZuwBAhmfdZj"


Token Generator Helper

Let’s say that you are using the Rails generator to create a new model and to specify the model attributes as part of the helper. For example:

rails g model user auth_token:token

Along with creating the relevant database migration, the model generator also automatically adds the has _secure_token: auth_token statement to your new model.


Deprecation of Relation#uniq

Rails 4.2 changed the uniq to distinct Active Record query method. The main reason for this was that uniq could be confused with the Array#uniq method; but distinct more closely matches the underlying SQL, which reduces confusion.


The old unique method was kept as an alias in Rails 4.2 but deprecated as of Rails 5.

Simply use distinct instead.


Required belongs_to Value

Prior to Rails 5, belongs_to values for models were optional. For instance, if I have an Orders model that specifies the relationship belongs_to: user, it would be possible for me to create an Order record with a nil user_id by simply not passing a value, or by setting it to nil. Although this is possible, this is rarely the desired behavior; it is quite likely an error.


Let’s clarify how it is normally used and how to make it explicit if nil is acceptable. In Rails 5, attempting to create a record with no associated record (i.e., having a nil value for the belongs_to attribute) results in a validation error.


However, if you wish for nil to be a perfectly valid value for your belongs_to attribute, you can specify that it is an optional value. To do this, simply add the optional keyword.


Listing Optional belongs_to in a Rails Model

class Order < ActiveRecord::Base

belongs_to :user, optional: true



For new applications created using Rails 5, this will be the default behavior. However, if you are upgrading an older application to Rails 5, this feature will be turned off by default, so as not to break existing applications.


If you wish to enable this feature in an application that was created before Rails 5, add the following setting to your config/application.rb file within the config block:

config.active_record.belongs_to_required_by_default = true


MySQL JSON Data Type

Version 5.7.8 of MySQL introduced support for a native JSON data type. While Active Record support for native JSON columns has existed for a while because it is a feature of PostgreSQL, this support is now extended to MySQL.


To create a new JSON column, simply specify the column type as json in your migration.


Listing Migration for a User with a Native JSON Column

class CreateUsers < ActiveRecord::Migration def change
create_table :user do |t|
t.json :settings


Let’s take a quick look at how to store and access data in a native JSON column. Let’s say that you have a User model created, as in the preceding example, with the settings column set to have a JSON data type.


To set values within the settings attribute, you can set it at create-time, directly using a hash. For example:

user.settings = { colours: ["red", "green"], alerts: true }
Or you can set it by using the key string as the accessor:
user.settings["colurs"] = ["red", "green] user.settings["alerts] = true
Obviously, setting values by specifying a hash overwrites any existing values unless you merge the new values with the existing ones.
To retrieve values, Rails returns the values of the JSON column as a hash. So for the previous example:
=> {"colours"=>["red", "green"], "alerts"=>true}
=> ["red", "green"]


Performing a database query based on the values of the JSON data differs from the PostgreSQL JSON implementation, so be aware that this feature is not completely compatible at the database level.


For instance, when using PostgreSQL, you can search within a JSON column called settings with

User.where("users.settings->>'alerts' = ?", "true")

whereas with MySQL you would use

User.where('JSON_EXTRACT(users.settings, "$.alerts") = true')


However, since querying based on the contents of a JSON column is not generally a great idea, hopefully, this isn’t something that you’ll have to deal with often. Adding indexes to JSON columns is possible, but it’s definitely simpler and better practice to use separate fields for those attributes that you need to search on.


Note Notice here that there are inconsistencies with how PostgreSQL and MySQL deal with Boolean values when searching within JSON data.


Enum Prefix and Suffix Definitions

Enums are a great feature of Active Record that allows you to represent a fixed set of attribute values for a given column as an integer in a database field. These values are then dynamically converted to and from the integer for both queries and results.


However, previously, it wasn’t possible to have the same enum values for different columns within the same model.


For instance, if you had a Post model with two columns, status and comments_ status, it would be impossible to use the same enum values, active and archived for both of them, because there would be a clash for the enum model instance methods, such as visible? and invisible? as demonstrated here:

class Post < ActiveRecord::Base
enum status: [:active, :archived]
enum comments_status: [:active, :archived] end
> post =


ArgumentError: You tried to define an enum named "comments_status" on the model "Post", but this will generate an instance method "active?", which is already defined by another enum.


Rails 5 solves this problem by adding: _prefix and: _suffix options to the enum definition.

These options can take either a Boolean value or a symbol.

If the Boolean true is used, the name of the enum is used as the prefix or suffice. If a symbol is used, that value is used as the prefix or suffix.


Listing. Post Model with Enums

class Post < ActiveRecord::Base

enum status: [:active, :archived], _suffix: true

enum comments_status: [:active, :archived], _prefix: :comments end


This now allows you to access the status and comments_status separately. Since the status enum specifies the _suffix as true, that means that the active! archived! active? and archived? methods are suffixed with the name of the attribute; that is, status. The following demonstrates this:

> post.status => "active"
> post.archived_status!
> post.active_status? => false
Since the comments_status attribute is defined as using the prefix comments, the ! and
? methods are referenced as comments_active and comments_archived, as shown here:
> post.comments_active!
> post.comments_status
=> "active"
> post.comments_archived? => false
Since you can set both _prefix and _suffix, you can create interesting enum definitions, such as:
enum font_size: [:small,:large], enum_prefix: :with, enum_suffix: true
This allows you to use instance methods such as this:


UUID Primary Keys

Rails 4 introduced native support for UUID primary keys when using PostgreSQL. However, even after enabling it, each time you create a new database table using the model generator, you must manually go in to edit each migration to set the id type to UUID.


Rails 5 introduces a new generator config option, primary_key_type.

By setting this to uuid, all newly generated migrations use a UUID as the primary key.


To make use of this, add the following configuration to your config/application.rb file within the config block.


Listing Setting the Generator to Use UUIDs As Primary Keys

config.generators do |g|

g.orm :active_record, primary_key_type: :uuid end


You also need to ensure that the uuid-ossp PostgreSQL extension is enabled.

If you haven’t already done this, you can use the enable_extension helper method. Create a migration and enable the PostgreSQL extension.


Listing Enabling UUID Primary Keys for PostgreSQL

class EnableUuidExtension < ActiveRecord::Migration def change

enable_extension 'uuid-ossp'



From here, creating a new model migration using the Rails generator results in migrations looking.


Listing Example Migration Using the UUID Primary Key

class CreateEvents < ActiveRecord::Migration def change
create_table :events, id: :uuid do |t|


Note Remember that for now, this is a PostgreSQL-only feature.


Left Outer Joins

A new method called left_outer_joins (and an alias left_joins) has been added to the Active Record query interface, allowing you to use SQL left outer joins. Previously, in order to perform outer joins, you had to use joins and raw SQL.


The current joins finder method should be used only for inner joins or for creating custom join queries, but any query requiring a left outer join should use the new method.


A query is previously written as

User.joins("LEFT OUTER JOIN orders ON orders.user_id =")

can now be written much more succinctly as this:



A common use case for left outer joins is when you wish to return a set of records, including those that do not have any related records in the join table.


For example, if you had a Users table in which each user could have many orders, to select all users together with a count of the total number of orders for each user, you could do this:


User.left_joins(:orders).select("users.*, COUNT(

AS orders_count").group('')


Users with no orders would still be present in the results, with an orders_count values of 0.

If you used the same query but with joins(:orders), any users with 0 orders would be missing from the returned results.
find_by Raises Exception


Not a big change, but one that should solve a few head-scratching moments!

The find_by and find_by! class methods now correctly raise an ArgumentError if they are called without any arguments.

Before, they would complain with NoMethodError: undefined method take!, causing some confusion.


Drop Table if_exists in Migrations

A useful addition to the migration drop_table statement is the if_exists option. When dropping an existing table in a migration, if the table has already been removed, then the migration will fail.


By adding the if_exists keyword, the table drop will only be attempted if the table actually exists.


So for example, to drop the orders table in your migration, you would use this:

drop_table :orders, if_exists: true


Validation Error Details

Rails 5 introduces a new option for returning the details of validation failures.

As you know, if an object fails validation, the reasons the object is invalid are accessible via the errors method. Before Rails 5, this could be serialized with just to_hash or full_messages.


These methods return the validation errors with the default error strings, custom messages defined in the validators, or localized strings based on the locale that is set. For instance:


{:email=>["can't be blank", "is too short (minimum is 5 characters)"]}


Rails 5 introduces a new details error serializer that returns the validation errors by returning a symbol representing the error, along with any additional details. The natural-language version of error messages is not returned.


For example, given the following model:

class User < ActiveRecord::Base
validates :email, presence: true, length: { in: 5..255 } end
An object with an invalid email attribute would return the following error details:
> user.valid? false
> user.errors.details
{:email=>[{:error=>:blank}, {:error=>:too_short, :count=>5}]}


This response is perfect for use in an API where you need to return validation failure information to the API client application but the client manages the localization of the error messages itself.


Note This behavior has also been backported for earlier versions of Rails and can be utilized by including the active_model-errors_details gem.


Support Bidirectional Destroys

In the previous versions of Rails, if you have two models related through a has_many/belongs_to relationship,

you cannot add dependent: :destroy to both of the relationships statements.


Attempting to delete either of these records results in a circular dependency, with each record attempting to delete the other one, ending in a Stack Too Deep error.


Rails 5 has addressed this issue and it is now possible to have models.


Listing Models with Bi-direction Destroy Dependencies

class Entry < ActiveRecord::Base
has_one :position, dependent: :destroy
class Position < ActiveRecord::Base belongs_to :entry, dependent: :destroy

Now, if you have an Entry record that has a related Position record, deleting either of the records will result in the deletion of the related record.



Since the first version of Rails, testing has been a fully integrated part of the framework. Over the years, the underlying libraries have been improved and the growing experience of Rails developers has meant that the recommended style of testing has been refined.


When Rails was first released, it made use of the Ruby Test:: a Unit library that was part of the standard Ruby libraries. Over time, many Rails developers moved to a new Behavior Driven Development test framework, RSpec.


However, with the release of version 4, Rails moved to MiniTest, a very fast and lightweight testing library. Many Rails developers have since switched from RSpec to MiniTest.


Although a significant number of Rails developers prefer to use RSpec, MiniTest is the default testing framework (and the one that is used to test Rails itself). MiniTest is part of the Ruby standard libraries.


It is very simple to understand and has a comprehensive set of features. Even if you’re used to using RSpec, it’s worth looking at MiniTest.


Rails 5 has received some nice improvements to the official test framework. The overall performance of test running has been improved in Rails 5, partly due to the speed increases across Rails and the move to Ruby 2.2, but also due to the performance investigations of the test stack and improvements made by Aaron Patterson and other Rails contributors.


In this blog, we look at the changes to the testing framework that you need to be aware of, plus a few nice improvements.


Test Runner

Rails 5 sports an all-new test runner through the improved rails test command.

As mentioned earlier in the blog, a number of tasks that were previously performed through the rake command have moved to rails. The test runner is one of them.


In earlier versions of rails, the entire test suite was run using rake test, or just rake on its own. Now, the entire test suite is run with the following command:

$ rails test


The test runner includes a number of very useful features and changes from the way test runs happened in earlier Rails versions.

As with other Rails commands, use the –h or --help option to get the full list of available options:

$ rails test --help


Defer Failure Output

If you run a test suite with failing tests, the first change that you’ll notice is that test failure is displayed as they happen, rather than being deferred to the end of the test run.

If you prefer the old-style behavior, you can use the -d or --defer-output option.


For any failing tests, along with details of the failure, now command is shown on how to run this failing test in isolation. For example:

# Running:
...F Expected: 200
Actual: 201
rails test test/controllers/todos_controller_test.rb:13


You’ll immediately notice that the failing test’s output display is now simpler and clearer, making it much easier to quickly understand how your test is failing.


Run Tests by Directory, File, or Line

The ability to run single tests in isolation directly from the command line is a very welcome improvement. It was possible in earlier versions, but it was not obvious and it required a number of command-line options.


Look at the following command:

rails test test/controllers/todos_controller_test.rb:13

It’s clear that it runs the test at line 13 of the test/controllers/todos_controller_ test.RB file. A copy and paste of that line are far simpler and faster now than it was previously.


In addition to being able to run a single test, you can also run all the tests in a file, such as this:

rails test test/controllers/todos_controller_test.rb

You can also run all of the tests within a directory. For example:

rails test test/controllers


Verbose Mode

While not specifically a feature of the test runner (the functionality comes from the MiniTest library itself), another useful feature is the verbose mode, enabled with the -v or --verbose option.


This prints the execution time for each test that is run. This— combined with being able to run a specific test file—can help you discover any particularly slow tests in your test suite.


For example:

 $ rails test test/controllers/todos_controller_test.rb -v
Run options: -v --seed 38407
# Running:
TodosControllerTest#test_should_get_index = 0.09 s = . 
TodosControllerTest#test_should_destroy_todo = 0.02 s = . TodosControllerTest#test_should_create_todo = 0.01 s =
 . TodosControllerTest#test_should_show_todo = 0.00 s = . TodosControllerTest#test_should_update_todo = 0.01 s = . 
Finished in 0.139012s, 35.9682 runs/s, 50.3554 assertions/s. 5 runs, 7 assertions, 0 failures, 0 errors, 0 skips


 Note If you wish to keep an eye on the performance of your tests, you should take a look at the minitest-profile gem.

With it installed, using the ––profile option will list the ten slowest tests at the end of each run.

You can learn more at Build software better, together means/minitest-profile.


Run Tests by Name

Another feature of MiniTest that is often overlooked (and which is now included in the test runner) is the ability to run tests by name. This -n option allows you to specify a regular expression and any tests that match this are executed. Again, this can really help with test development and debugging.


Remember, because you are passing in a RegEx, if you require matching a test name on something other than an exact match, you need to surround the search string with /. For example:

$ rails test -n /show/

Run options: -n /show/ --seed 35219

# Running:

Finished in 0.135740s, 7.3670 runs/s, 7.3670 assertions/s. 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

You can also specify a string with the –n argument, but this string must be an exact match with the test that you wish to run, so it’s much more commonly used with regular expressions.


Fail Fast

Another great feature of the test runner is the option to fail fast.

This mode is enabled with the -f or --fail-fast option.


When enabled, the execution of the test suite is aborted as soon as a test failure is encountered. If you have a test suite that takes a long time to run, this could save you some time.


Colored Test Output

One last hint: you can produce a colored output by specifying the -p or --pride flag.


Controller Request Named Parameters

Rails 5 brings a simple but welcome change to the helper methods used for the HTTP request tests in controller tests.


In previous versions of Rails, the get, post, put, patch, delete, and head methods took the name of the controller action to call, followed by a number of options arguments: request parameters, session variables, and flash values.


But these optional values always had to be in that order, and if you wanted to omit one, you had to use a nil value.


For example, to call a get method with no parameters but with a flash message, you would have to use this:

get :index, nil, nil, { message: "Welcome" }


The multiple nil arguments present in the states make the request confusing to read and it’s all too easy to miss a nil when writing tests.

Rails 5 allows you to pass in these optional arguments as keyword arguments, so the preceding request would be rewritten as follows:

get :index, flash: { message: "Welcome" }
To simulate a request with parameters, use the params keyword:
post :create, params: { name: "Fred" }
You can use the keywords params, session, flash, body, xhr, and format with the
HTTP test helpers, as can be seen in the following examples:
get :show, params: { id: 31 },
session: { user_id: 9 },
format: :json
post :create, params: { user: { name: "Fred" } },
flash: { message: "User created" }
This also means that the xhr helper has been removed in favor of using the xhr keyword. So, for instance,
xhr :post, :create, params: { name: 'Alan' }
post :create, params: { name: 'Alan' }, xhr: true


The use of keyword arguments makes your tests clearer and easier to read and understand.

For the moment, the old-style still works, but it’s likely that it will be deprecated in the future, so it’s worth moving to the new syntax for new tests.


Deprecation of assert_template and assigns

If you are already using MiniTest and have a comprehensive test suite, one change that is likely to affect you is that the controller test assertions assert_template and assigns have been deprecated.


Depending on how you previously approached testing controllers, this may or may not be concerning, but in my experience, a lot of teams rely heavily on both of these in their controller tests.


The reasoning behind the removal of both of these is mainly due to an evolution of how the Rails core team believes controller testing should be done. Controller tests should be concerned with what the responses of the controller methods are, not the internal details of how the response was created.


assert_template and assigns are both used to test implementation details rather than what is actually produced as a result of the request.


If a view is abstracted into partials, then any assert_template tests are likely to break, even though the end response is the same. Which instance variables are set through the use of assigns should not be a concern of your test.


A controller test should be testing the following:

  1. That the HTTP status code is correct
  2. That the rendered output contains the correct data and DOM elements
  3. Changes to the persisted data


So, rather than checking that an instance variable was set, you should use assert_select to check if the expected data is present in the rendered output. This output may be HTML, but the same applies to test an API response in JSON, in which case the JSON response would be parsed and the expected data matched.


It could be debated that this style of testing is much closer to an integration test than a unit test for a controller; that is, we are testing a request from beginning to end, ensuring all of the pieces are working together.


Integration tests in earlier versions of Rails tended to be slow to run, but as a result of the performance improvements in Rails 5, this is no longer an issue.


Note If you absolutely must continue to use assert_template and assigns, then you can simply use the rails-controller-testing gem, which restores the functionality. The homepage for the extracted implementation is at Ruby on Rails rails-controller-testing.


This change also affects RSpec, since it expects both of the assertions to be available. At the time of writing, the RSpec project is planning to automatically include the rails-controller-testing gem, if necessary.



Although a lot of people prefer to use factories for creating model data for their test cases, fixtures are still a very fast, simple, and powerful way to create model test data. The release of Rails 5 comes with a few nice enhancements to fixtures.


Fixture Model Class

There is now an optional special key settable in a fixture file to specify the model class name. So if you are using a database table that is named something different from a pluralized version of the class name, you can specify it using the following:




name: Alan


This was possible in earlier versions by using set_fixture_class within the test case class itself. However, since this setting is related to the fixture rather than the test case, and having it set in the test case precludes fixtures being properly loaded by the task db:fixtures: load, this fixture’s metadata has been moved into the fixture file itself.


The old method isn’t marked for deprecation just yet, but if you make use of this feature, it’s probably a good idea to start using this method instead.


Enum Values

Enums are a sometimes overlooked feature of Active Record, allowing you to use integer database columns to represent a fixed set of values for a model attribute.


Previously, if you used enum attributes in your model when creating a fixture for that model, you had to use the equivalent integer value of the required value of the enum attribute. This made the fixtures less readable resulting in wasted time having to refer back to the enum definition.


Rails 5 allows you to use a symbol or a string of the enum value rather than the integer representing that value.


For instance, your model defines an enum attribute as follows:

enum :language, [:english, :french]


Whereas previously, you would have to know that English is the first enum value, therefore having the value 0, you can now write the fixture as follows:


name: Fred

language: :english

Request via Redirect Deprecation


Another deprecation in Rails 5 is a change to the integration test helpers.


In Rails 5, the request_via_redirect integration request helper and all of the associated methods for each of the HTTP request methods (such as post_via_redirect) have been removed.


This method was most often used to allow you to perform request such as post_via_redirect or patch_via_redirect, which performed the request and then followed any subsequent redirects. Since that is reasonably common behavior for web applications after a POST or PATCH request, it is often found in integration tests.


Thankfully, it is a simple change to continue testing this. All you need to do is perform the desired HTTP request and then manually call follow_redirect! directly afterward.


Rails API

While Rails is generally used to develop web-based applications, the increasing requirement to build API-only services has resulted in many people using Rails to build apps that have no web front end at all.


While this is certainly possible, it means that there are often a lot of unused gems and middleware overhead, slowing it down and getting in the way. In order to make API application development simpler, Rails 5 has merged the Rails API project into Rails.


Using Rails for API Servers

Back in 2004 when Rails was first released to the world, the connected world was a very different place.


Very few websites offered API access and those that did usually exposed the API using SOAP, XML-RPC, CORBA, or their own unique quirky API protocol. There was no common consensus on authentication methods, so some allowed tokenized access and some relied on HTTP Basic. The output of the APIs was usually XML.


While both the RESTful architecture style and JSON as an output format had been around for many years, neither had yet been universally adopted by the web development community.


The majority of mobile phones had small 128×128 pixel displays, the 3G rollout was still in the very early stages (and the corresponding data allowances were tiny and expensive) and most mobile application developments was limited to small J2ME applications with limited functionality. Therefore, the developer demand for APIs was still small.


Web applications all used the traditional full-page reload for each request and use of JavaScript was limited to small, snippets of functionality.


However, obviously, a lot has changed since then. The use of connected devices has grown astronomically in the last decade, meaning your application is likely to require an API for iOS and Android applications.


It is now common to be requested to build a purely API-driven application that has no web interface at all, both to serve as back ends for mobile and desktop apps.


Advances in JavaScript mean that it’s now possible to build highly interactive, complex browser interfaces that purely use the server via an API rather than relying on traditional HTML server responses.


Also, the rise in adoption of microservice architectures means that more than ever, Rails is being used to build API-only applications.


Rails have long provided ways of allowing the creation of APIs, but with the inclusion of the Rails API project into Rails itself, there is now a standardized way of doing this.


The Rails API Project

The Rails API project started in 2012 as a gem that provided a way to generate a Rails application excluding parts of the framework that aren’t necessary to create an application with no HTML front end.


Over time, it kept up with the Rails releases, became more configurable and now, with the release of Rails 5, has been merged and become part of the framework itself.


JSON Response Creation

By default, a Rails 5 API-only application just relies on the to_json method of each model to generate the JSON output, but you will likely want to make use of a serialization library such as JBuilder or Active Model Serializers.


In this blog, we will look at the Active Model Serializers gem. The Active Model Serializers library was part of the Rails API project and was originally planned to be the default for Rails 5 API applications, but this was changed in the Rails 5 beta releases and now it ships with no default library.


Active Model Serializers

Active Model Serializers (often referred to as AMS) allows you to easily create serializers for Active Model objects, encapsulating all of the serializer logic for each model.


Out of the box, Active Model Serializer understands Active Model objects and it follows the Rails convention of using current_user for the authenticated user object. Because of this, creating JSON or XML serializers for APIs is made elegant and simple.


Most interestingly, maybe, is the support of the JSON API adapter. The JSON API project is an attempt at creating a standard convention for JSON API responses.


This includes standard syntax for embedding related objects, links to other objects and pagination links. AMS allows different adapters to be used, so the use of the JSON API adapter is not mandatory; by default, a simple attributes adapter is used.


While there are a vast number of alternative JSON serializer projects, AMS has gained a huge following and has become the preferred solution for a large number of developers.



If you’ve ever built an API as part of a team, you’ll likely be familiar with the amount of time going back and forth between server and client developers about how the API should function, the format of the JSON responses, how pagination should work, if you should use IDs or URLs to resources, etc.


JSON API is a specification for how a modern JSON API should work, based on the experience of building real-world applications. By defining a clear and sensible set of guidelines, developers can spend less time debating the API format and more time building the application.


The JSON API specification was originally designed by Yehuda Katz who designed the specification originally as part of the Ember framework (a JavaScript web application framework). He wanted to define a standard format to allow backend applications to be compatible with Ember applications running client-side.


Since, at the time, Rails applications with APIs tended to have interfaces that were RESTful, but didn’t adhere to any particular standard, he decided to create his own.


That project gained adoption outside of Ember and version 1.0 of the JSON API specification was released in May 2015.

There are libraries available for many platforms and languages that allow client and server developers to easily implement a JSON API compatible API.


You can read more about the JSON API specification at A specification for building APIs in JSON and see a list of the available implementations at JSON API - Implementations.


Why Use Rails for an API Application?

If you are considering building an API-only application, you may automatically consider a framework such as Sinatra or Grape, because people often consider Rails too heavy for an API app.


However, if you’ve ever done just this unless your application is very simple, you often find that you end up having to reimplement features that are provided by the framework in a Rails app.


Features like having built-in support for live reloading; providing different environments for development, testing, and production; simple routing; URL generation; and parameter parsing. Of course, Rails also provides great security support and authentication features.


Plus, if you are already familiar with building applications in Rails, it’s incredibly convenient to be able to use the same tools that you already know well.


So, yes, while you certainly can use a smaller, lighter framework to write an API application, having the Rails toolset backing you up makes life a whole lot easier and allows you to be more productive.


Building an API Application

Let’s go ahead and create an API-only Rails application. This is done using the usual rails new command but with the addition of the --API option. For example:

$ rails new TodoApi --api


First, open up the project’s Gemfile. You’ll immediately notice that this is a lot lighter than the regular Gemfile generated for a new Rails application. All the gems related to web interfaces such as jQuery, CoffeeScript, and the asset pipeline are omitted.


As mentioned earlier, no serialization gems are included in the default Gemfile, so you should add the AMS gem and bundle install now:

gem 'active_model_serializers'


If you look at the generated Application Controller at app/controllers/ application_controller.rb

you’ll see that that class inherits from ActionController:: API (rather than the usual ActionController:: Base)


Listing The Generated API Application Controller

class ApplicationController < ActionController::API end


This class definition is also missing the protect_from_forgery statement that is usually included, which is used to detect CSRF attacks. Since this only relates to web forms, it is not necessary for an API-only application.


If you take a look at the generated config/application.RB file, you’ll see the following option:

config.api_only = true


As discussed earlier, this limits what middleware is loaded. Some of the middleware that is excluded are things like cookies, sessions, and flash messaging. If you require any of these in your application, you can always re-enable them by using, for example:


config.middleware.use ActionDispatch::Cookies

could be added to your config/application.rb file.


Also, you’ll notice that where the application.RB file usually contains the statement require 'rails/all', the API application lists the individual frameworks that are loaded, allowing you finer control over while parts of Rails are required for your application.


You may have noticed that the generated application is missing the directories app/assets, app/helpers, and app/views. Since these directories are all related to applications with web interfaces, they are simply omitted from any apps generated with the Rails API option.


So now that we know our way around the generated application, let’s create a simple API-only project. I will use a simple to-do application as an example, where a todo model will have a title and a completed at the timestamp.


We can use the rails generate a command in the same way as we would for a regular Rails application. Using generate scaffold:

$ rails g scaffold todo title completed_at:timestamp
invoke active_record
create db/migrate/20151012134203_create_todos.rb
create app/models/todo.rb
invoke test_unit
create test/models/todo_test.rb
create test/fixtures/todos.yml
invoke resource_route
route resources :todos
create app/serializers/todo_serializer.rb
invoke scaffold_controller
create app/controllers/todos_controller.rb
invoke test_unit
create test/controllers/todos_controller_test.rb


This generated code is a fully working API application. Let’s take a look at what was generated and how it differs from a traditional Rails app.


The generated migration and model, model test file and addition to the routes.RB file is exactly the same as those that would be created for a normal Rails web application.


However, the controller, serializer, and controller test files are rather different than if we ran the generator without the api_only setting enabled. Also, you’ll note that there are no view files, as the only output of our application will be created by specifying a response in your code or calling the relevant serializers.


Let’s look at the generated serializer.


Listing The Generated TodoSerializer

class TodoSerializer < ActiveModel::Serializer attributes :id, :title, :completed_at



As you might expect, this means that the object is serialized by including the attribute’s id, title, and completed_at values. You can extensively customize the output of the serializer.


Naturally, you can remove any attributes from this list if, say, there are fields used internally that shouldn’t be exposed via the API. You can also add additional attributes that are method calls on the object or are just methods within the object’s serializer class.


For example, if we wished to add a Boolean attribute called completed, we could do this by adding a completed instance method to either the model or the serializer and then adding this attribute to the list in the serializer definition.


Example of a TodoSerializer with a Custom Attribute

class TodoSerializer < ActiveModel::Serializer attributes :id, :title, :completed_at attributes :completed
def completed


You can change the name of an attribute by specifying the key for a particular attribute. For example, we could change the name of the completed_at attribute to be finished_at in the output by changing the serialization attributes.


Listing Example of TodoSerializer with a Renamed Attribute

class TodoSerializer < ActiveModel::Serializer attributes :id, :title

attribute :completed_at, key: :finished_at end


It is also possible to embed associations within the JSON output by simply adding has_many (or has_one) and belongs_to to the relevant serializers. For example, if our application had a notes model, and each todo item could have one or more notes, you could include the relevant notes within the JSON output for a todo item by adding a has a _many statement to the serializer.


Listing Example of TodoSerializer with Embedded Notes

class TodoSerializer < ActiveModel::Serializer attributes :id, :title, :completed_at has_many :notes


Let’s now take a look at the controller created by the scaffold generator.

The Scaffold Generated TodosController

class TodosController < ApplicationController
before_action :set_todo, only: [:show, :update, :destroy]
# GET /todos def index
@todos = Todo.all
render json: @todos
# GET /todos/1 def show
render json: @todo end
# POST /todos
def create
@todo =
render json: @todo, status: :created, location: @todo else
render json: @todo.errors, status: :unprocessable_entity end
# PATCH/PUT /todos/1 def update
if @todo.update(todo_params) render json: @todo
render json: @todo.errors, status: :unprocessable_entity end
# DELETE /todos/1
def destroy
# Use callbacks to share common setup or constraints between actions. def set_todo
@todo = Todo.find(params[:id]) end
# Only allow a trusted parameter "white list" through.
def todo_params
params.require(:todo).permit(:title, :completed_at, :position) end

You may notice some interesting differences from the controllers you are used to seeing generated by Rails. First, each action has a render json: statement rather than relying on Rails to find the relevant view file.


Next, there are no “edit” or “new” actions in the controller. This is because in a pure API application there is simply no need for these requests.


An HTML based web application requires new and edit actions to provide users with a form that allows them to enter and submit data to the server’s create and update actions respectively. In an API, the API client can just access those methods directly with no need for a form.


Another interesting thing to note is that the render methods called in the create action include both status and location in the response, along with returning the created object as JSON (which is of course defined by the serializer).


This is the expected behavior for a RESTful API: the 201 Created HTTP status is returned, the URI for the created resource is returned in the HTTP headers and the created resource in the body.


Let’s spin up the application and look at how it responds.

Perform the pending database migrations with this:

$ rails db:migrate
And then start the server with this:
$ rails s
Now we can attempt some API requests using cURL:
$ curl -H "Content-Type:application/json" -X POST -d '{"todo":{"title": "Write a blog"}}' http://localhost:3000/todos
"id": 1,
"title": "Write a blog",
"completed_at": null


Note I have formatted the response from cURL as to make it easier to read. When manually testing and investigating APIs, I’d highly recommend using a tool such as Postman for Chrome (Postman) or Paw for OS X (Paw – The most advanced API tool for Mac).


Note that since we are sending the data as JSON rather than a form post or as URL parameters, we need to set the Content-Type header to application/json. Without this, Rails will not correctly parse the data sent with the request.


The response to a POST from the controllers from by the scaffold generator is to return the object just created. This is generally good practice to stick with this unless you have a specific use case.


Returning the created resource is important so that the client can confirm that all the values have been stored correctly if any additional values have been set by the server if any values have been transformed, and importantly, inform the client of the id of the object. Obviously, you can change this response behavior in the controller.


Now that we have created a todo item, we can retrieve the list of objects via the index method.

$ curl http://localhost:3000/todos
"title":"Write a blog",


As expected, an array is returned with each item listing the attributes, which are listed in the TodoSerializer. As described earlier, you can add, remove, or transform attributes from there.


Active Model Serializer Adapters

Earlier, I mentioned that Active Model Serializer uses adapters to describe how the attributes and object relationships should be serialized, therefore providing support for different styles of API responses. Let’s look at how these can be used and affect the output.


By default, Active Model Serializers use AttributesAdapter, which is a very simple adapter that provides basic JSON serialization, but without a root key. If you require a root key in the JSON output, you can use the alternative JSON adapter.


To do this, create a new initializer called config/initializers/api_adaptor.rb containing the following line:

ActiveModel::Serializer.config.adapter = :json

Restart your Rails server and retry the cURL index request. The returned JSON will be as follows:

"todos": [
"id": 1,
"title": "Write a blog",
"completed_at": null


Now, the root key of the returned object is the name of the object’s class. However, this is still a pretty limited API implementation, since you still have to decide on, adapt, and implement other specifics of your API, such as how pagination works, how errors are returned, and how related and nested objects work.


As discussed earlier, the JSON API specification aims to improve this situation by describing how an ideal API should work in regards to things like pagination and relationships.


Active Model Serializer includes an adapter called JsonApiAdapter, which helps you easily implement an API that conforms to the JSON API specification. The Active Model Serializer gem developers recommend the use of the JSON API adapter over the basic attributes adapter or JSON adapter because it is the most fully featured and actively developed adapter.


Obviously, depending on your application requirements, using the JSON API standard may not be possible for you, but if you are building a greenfield API, you should strongly consider it.


So, let’s make a few changes to the app. First, enable the JsonApiAdapter by changing the config/initializers/api_adapter.rb to the following:

ActiveModel::Serializer.config.adapter = :json_api


Now, let’s add pagination to the index request. The AMS JsonApiAdapter supports both Kaminari and WillPaginate gems. In this example, I’ll use Kaminari. Add the gem to your Gemfile as follows:

gem 'kaminari'


Then perform a bundle install.

The JSON API specification recommends that servers use the page parameter name for pagination operations, so we will use page[number] for the page number and page[size] for the number of items per page.


Since Kaminari sets a default if a nil page number and the page size is passed, we can simply change our TodoController index method.


Listing The TodoController Index Method with Pagination

def index
if params[:page]
page_number = params[:page][:number]
size = params[:page][:size]
@todos =
render json: @todos


If no page parameter is supplied at all, both the page number and the page size are set to the default.

After restarting the server to pick up the initializer change, reload the todo index. To make the pagination examples clearer, I have added some additional todo items.

$ curl http://localhost:3000/todos
"data": [
"id": "1",
"type": "todos",
"attributes": {
"title": "Write a blog",
"completed_at": null
"id": "2",
"type": "todos",
"attributes": {
"title": "eat dinner",
"completed_at": null
"id": "3",
"type": "todos",
"attributes": {
"title": "walk the dog",
"completed_at": null
"links": {}


You’ll notice that the output is rather different from the simple JSON adapters we used earlier. Following the JSON API specification, rather than having the root key as the resource name, or simply nothing, it has the key data.


Then, the resource data lists the id, the type (i.e., the name of the resource object), and attributes as the attributes of the resource.


To see the effect of adding pagination and how the links appear, repeat the index call with small page size and on the second page, as follows:

$ curl –-globoff http://localhost:3000/todos?page[size]=1&page[number]=2
"data": [
"id": "2",
"type": "todos",
"attributes": {
"title": "eat dinner",
"completed_at": null
"links": {
"self": "http://localhost:3000/todos?page%5Bnumber%5D=2&page%5Bsize%5D=1",
"first": "http://localhost:3000/todos?page%5Bnumber%5D=1&page%5Bsize%5D=1",
"prev": "http://localhost:3000/todos?page%5Bnumber%5D=1&page%5Bsize%5D=1",
"next": "http://localhost:3000/todos?page%5Bnumber%5D=3&page%5Bsize%5D=1",
"last": "http://localhost:3000/todos?page%5Bnumber%5D=3&page%5Bsize%5D=1"


Note In the previous cURL example, it was necessary to use the option --glob off because, otherwise, the characters [ and ] are interpreted by cURL itself and the command fails.

This option disables the “URL globbing parser” for cURL.


The links hash has values for self, first, prev, next, and last. The client application can then step through the pages as necessary.


If an object has relationships and they are specified in the serializers, the related object types and ids will be detailed in the JSON API response. For instance, if our todo items could have multiple notes added to them, our TodoSerializer would look as shown in Listing 5-8.


Listing Adding a Relationship to the TodoSerializer

class TodoSerializer < ActiveModel::Serializer attributes :id, :title, :completed_at has_many :notes


A NoteSerializer would detail the reciprocal relationship.


Listing The NoteSerializer Class

class NoteSerializer < ActiveModel::Serializer attributes :body
belongs_to :todo
Now, a request for the detail of a todo object includes a relationships key, as shown here:
"data": {
"id": "1",
"type": "todos",
"attributes": {
"title": "Write a blog",
"completed_at": null
"relationships": {
"notes": {
"data": [
"id": "1",
"type": "notes"

However, this currently means that the client would have to perform a separate request to get the detail on the note with id 1.

AMS also supports nested resources. This is a very useful feature to allow clients to request documents with related objects included in the JSON response.


Depending on how the data is structured and how the client application works, the client may be able to perform fewer API requests to present the necessary data.


If we wished to include all related notes objects in our response, we can add the include argument to the render statement, as follows:

render json: @todo, include: 'notes'
This would result in the following response:
"data": {
"id": "1",
"type": "todos",
"attributes": {
"title": "Write a blog",
"completed_at": null
"relationships": {
"notes": {
"data": [
"id": "1",
"type": "notes"
"included": [
"id": "1",
"type": "notes",
"attributes": {
"body": "this is important"
"relationships": {
"todo": {
"data": {
"id": "1",
"type": "todos"

Now the client can match up the related note with the respective todo object.

The include argument can be either a string or an array; AMS parses it as necessary. As suggested by the JSON API spec, you can request an include nesting associated object too;

for example, if you were rendering a number of items, you could include the associated review objects and the author objects associated with those reviews, as follows:


render @items, include: 'reviews,'


Obviously, this may potentially result in some queries taking longer than required, so consider this carefully.


You can also use a wildcard option ( *), which includes the immediately associated objects; ** recursively includes all nested objects. Again, this could very well cause some performance issues if implemented carelessly.


Since AMS accepts a string, it is possible to just pass params[: include] to the render statement; however, you should never do this without carefully considering the implications of a user requesting a recursive wildcard. Filter and sanitize as necessary!



Active Model Serializers also supports the caching of responses. It uses the configured Rails cache store in the same way as for view caching works. To enable caching, simply add the cache statement to a serializer and specify a key that will be used to generate the cache key.


To demonstrate this, let’s leave the development cache store as the default “memory store,” and enable caching in development mode with the following command:$ rails dev: cache


Development mode is now being cached.

You must restart your rails server to pick up the change to cache configuration. The server must also be started with the -C or --dev-caching options to allow the server to use a cache in development mode.


 Now enable caching responses of the Todo serializer by adding the cache statement to the serializer class.


Listing  Adding Caching to the TodoSerializer

class TodoSerializer < ActiveModel::Serializer cache key: 'todo', expires_in: 24.hours attributes :id, :title, :completed_at has_many :notes


As each todo object response is initially rendered, it is cached with the key "todo/#{}-#{todo.updated_at}". Since the updated_at timestamp is part of the key, this means that the key is changed whenever the object is updated.


This means that we don’t need to worry about manually expiring the object at all. In this example, I’ve set the optional cache setting expires_in so that the cached data is automatically expired after one day.


It is also possible to partially cache objects by specifying only or except arguments to the cache statement. For example, if you only wished to cache the title attribute of each todo item, you would change the serializer cache statement to this:

cache key: 'todo', expires_in: 24.hours, only: [:title]


When planning your API application caching strategy, you should also consider using supporting HTTP conditional GETs using the ETag or Last-Modified headers. These are described in the official Rails caching guide at caching_with_rails.html.


Action Cable

Action Cable is one of the most exciting features of Rails 5. Action Cable allows you to easily add real-time, full-duplex communication to you Rails application, allowing us to build pages that are updated dynamically.


Action Cable uses the WebSocket protocol to enable our server to send real-time messages to individual users or broadcast messages to all currently online users.


It provides a very “Rails-like” interface for the entire WebSocket front-end and back-end code, making it very easy for existing Rails developers to add functionality that was previously complex or simply not possible with just Rails.



Depending on your choice of Rails web server (i.e., Puma, Unicorn, etc.) and how your environment is configured, your application will only have a handful of open and active communications channels at any one time.


WebSocket presents a very different way of communicating between your application and the client’s browser. The WebSocket protocol is a full-duplex communication channel between your application and the user’s browser. This connection uses TCP and runs over port 80, the same as HTTP, but the way it works is very different.


Rather than requiring the client to initiate separate HTTP requests each time that it wishes to send or receive data, it opens a connection to the server that stays open for the duration of the session—that is, until the user navigates away from the page or closes the browser tab.


Once the connection is open, both the server and the client can exchange messages at any time, irrespective of user input.


On the client side, you write JavaScript code to execute when a WebSocket message is received, on the server side, Action Cable allows you to write Ruby methods to handle received messages in a very similar way that you would process an HTTP request.


The WebSocket protocol uses ws:// and wss:// prefixes to indicate insecure and secure WebSocket connections, respectively.


The architecture of an Action Cable Application

A Rails app that involves an Action Cable component is a little more complicated than a traditional HTTP request-response application.


First, there is the main Rails application itself. This is no different from any normal Rails application. It’s possible to add Action Cable feature to any Rails application once it has been updated to Rails 5.


The Action Cable specific code is then separated into app/channels for the back-end Ruby code and app/assets/javascript/channels for the client-side JavaScript or CoffeeScript code.


While it is certainly possible to go crazy and build your entire application around WebSocket connections, it is designed for and works best when the functionality is added selectively to parts of your application that require this kind of feature.



Action Cable is based around the Publish-Subscribe messaging pattern, often referred to as Pub/Sub or simply pubsub.


This is exactly as it sounds: it allows a publisher (in our case, the Action Cable part of your Rails application) to publish “messages” via a channel to any subscribers (in our case, the client browsers that are subscribed to the relevant channels.).


Clients can subscribe and unsubscribe to channels as necessary and only receive messages for the channels they are subscribed to.



When a browser loads a page that you have enabled Action Cable on, it will attempt to open a “connection” with the Action Cable server.


For each incoming WebSocket connection, the server instantiates an Action Cable connection object that is used to authenticate and identify the user if necessary.


This instance becomes the parent of all the channel subscriptions for that client to the Action Cable server. The connection itself only deals with authentication and authorization.


This connection code is specified in app/channels/connection.rb and there will generally be only one Connection class per application.



Your client-side application only opens one Action Cable connection to the server, but then can subscribe to a number of channels via this connection. It can then use each of these channels to send and receive messages to the server.


In your Rails Action Cable server code, you define a number of channel classes. Each channel should be used to communicate a particular specified activity or type of event.


For example, you may use CommentsChannel to listen for and display new comments are they are created, or OnlineStatusChannel to listen for users coming online or going offline to update an on-screen list.


Since the WebSocket Connection class is bidirectional, your client application can use these channels to listen for incoming messages and transmit messages back to the Action Cable server.


Rails 5 WebSocket Implementation Details

In order to enable a WebSocket application to be built using Rails, Action Cable makes use of a number of other dependencies. In particular, it requires a subscription service and a Rails application server to handle the WebSocket requests.


In the initial versions of Action Cable, Redis was the only supported Pub/Sub server, but now many different types of adapters ship with Action Cable, including support for asynchronous, inline, PostgreSQL, even Redis, and non-vented Redis.


You can use the same Rails application server for both your core Rails application and also the Action Cable server, but while this is definitely suitable for use during development and for deployment of smaller sites, you may wish to consider using a separate application server processes for the main web application and the Action Cable server.


This will allow you to monitor and tweak each separately to handle the load specific to your site.


Pub/Sub Back End

Action Cable requires a Pub/Sub service to be available for use as the back-end messaging system. At the time of writing, Action Cable supports Redis and PostgreSQL, along with asynchronous and inline adapters.


You may have come across Redis before and quite possibly used it in a Rails application as it is commonly used as the backing for Rails cache storage, but it also features a very fast and stable implementation of Pub/Sub.


PostgreSQL 9.1 introduced a Pub/Subsystem that can also be utilized for Action Cable. Since the back-end services are abstracted with adapters, you can easily change the back-end service and test to find out which performs better for your requirements.


The Async and Inline adapters are designed for use in development mode, allowing you to use the same Rails server as the Action Cable server.