What makes Rails a great framework
to work with is
conventions over configuration.
Rails community is always striving
to keep these conventions relevant
In this blog, we will see
why and what changed in
execution order of
protect_from_forgery protects applications
Follow that link to read up more about CSRF.
If we generate a brand new Rails application in
Rails 4.x then application_controller will look
Looking it at the code it does not look like protect_from_forgery is a before_action call but
in reality that’s what it is. Since protect_from_forgery is a before_action call it should follow
the order of how other before_action are executed.
But this one is special
in the sense that
protect_from_forgery is executed first in the series
of before_action no matter where protect_from_forgery is mentioned.
Let’s see an example.
In the above case even though protect_from_forgery call is made
after load_user, the protection execution happens first. And we can’t
do anything about it. We can’t pass any option to stop Rails from doing
a boolean option called prepend.
Default value of this option is false.
What it means is, now protect_from_forgery
gets executed in order of call.
Of course, this can be overridden
by passing prepend: true as shown below and now
protection call will happen first just like Rails 4.x.
There isn’t any real advantage
to be the first filter in the chain of filters to be executed.
On the flip side,
there are cases where
output of other before_action
should decide the execution of protect_from_forgery.
Let’s see an example.
Above code would fail in Rails 4.x,
though called after :authenticate,
actually gets executed before it.
Due to which we would not have
@authenticated_by set properly.
Whereas in Rails 5, protect_from_forgery
gets executed after :authenticate
and gets skipped if authentication is oauth.
Upgrading to Rails 5
Let’s take an example
how this change
the upgrade of applications
from Rails 4
to Rails 5.
In Rails 4.x, set_access_time
is not executed for bad requests.
But it gets executed in Rails 5
because protect_from_forgery is called
Saving data (current_user.save) in before_action
is anyways a big enough violation
of the best practices,
but now those persistences
would leave us vulnerable
to CSRF if they are called before
protect_from_forgery is called.
UUIDs are a popular alternative to
auto-incremental integer primary keys.
Notice that id: :uuid is passed to
This is all we need to do
to have UUID as primary key for users.
Now, if an application is designed
to use UUID instead of Integer,
then chances are that
new tables too would use UUID as primary key.
And it can easily get repetitive
to add id: :uuid
in create_table ,
every time a new model
Rails 5 comes up with
We need to set primary key as UUID
This automatically adds
id: :uuid to create_table
in all future migrations.
If we are using the latest version of PostgreSQL then we should enable
pgcrypto extension as per Rails guide.
extension we need a migration which does something like this.
In Rails 4.x the default queue adapter is :inline.
In Rails 5 it has
been changed to:async by DHH.
In case of inline, as the name suggests, execution of the job
happens in the same process that invokes the job.
In case of Async adapter, the job is executed asynchronously using in-process thread pool.
AsyncJob makes use of a
thread pool and the data is retained in memory.
Since the data is stored in memory, if the application restarts, this data is lost.
Hence, AsyncJob should not be used in production.
Running in future
AsyncJob supports running the job at some time in future through perform_later.
Inline executes the job immediately and does not support running the
job in future.
Both Active Job Async and Active Job Inline do not support configuring priorities among queues,
timeout in execution
and retry intervals/counts.
Advantage of having Async as default adapter
In Rails 4.x where Inline is the default adapter, the test cases were mistakenly dependent on job’s behavior
that happens synchronously in development/testing environment.
Using Async adapter ,by default, will help users have tests not rely on such synchronous behavior.
It’s a step closer to simulating your production environment
where jobs are executed asynchronously with more persistent backends.
Consider an example, where in an e-commerce site upon every order placed an email is sent.
The process of sending email can be part of a job which is invoked from an after_create callback in Order model.
When Inline adapter is used, any wrongly configured email settings will cause both the above tests to fail.
This is because the process of sending the email happens within the process of order creation and any error in sending
the email would kill the process if unhandled.
short for entity tag,
is a part of HTTP header and is used for web cache validation.
ETag is a digest of the resource that uniquely identifies specific version of the resource.
This helps browser and web servers determine
if resource in the browser’s cache
is exactly same as
the resource on the server.
Strong ETag indicates that resource content is same for response body
the response headers.
Weak ETag indicates that the two representations are semantically equivalent.
It compares only the response body.
Weak ETags are prefixed withW\
thus one can easily distinguish between Weak ETags and Strong ETags.
page to illustrate how ETag matching works.
When server receives a request, it returns an ETag header as part of HTTP response.
This ETag represents state of the resource.
For the subsequent HTTP requests,
client sends this ETag via If-None-Match header to identify if the resource is changed or not.
The server will compare the current ETag and the one sent by the client.
If ETag matches, server responds with 304 Not modified.
This means resource content in the client’s cache is up-to-date.
If resource is changed, server will send updated resource along with the new ETag.
Let’s see it in action.
ETags in Rails 4.x
Rails 4.x generates strong ETags by default i.e without W/ prefix.
We are making first request to the server.
For the next request,
we will send ETag that was sent
by the sever.
And notice that server
304 Not Modified.
Now for the second request, server will return 304 Not Modified response as before,
but the ETag is weak ETag.
Why this change?
Rails does not perform strong validation of ETags
as implied by strong ETags spec.
Rails just checks
whether the incoming ETag from the request headers
matches with the
ETag of the generated response.
It does not do byte by byte comparison of the response.
This was true even before Rails 5.
this change is more of a course correction.
Rack also generates weak ETags
by default because of similar reasons.
Rails 4.x returns error information in HTML page
whenever there is any exception,
in the development environment.
This is fine for normal HTML requests.
But traditionally, Rails always returned with HTML response
for exceptions for all requests, including JSON on XML requests
We can now generate API only apps in Rails 5.
In case of such apps,
to have the error message
in the format in which request was made.
Having an HTML response for a JSON endpoint
is not going to help in debugging why the exception happened.
New config option debug_exception_response_format
Rails 5 has introduced new configuration
to respond with proper format for exceptions.
Let’s see an example of the response received with this configuration.
The status key will represent HTTP status code
and error key will represent the corresponding Rack HTTP status.
exception will print the output of actual exception in inspect format.
traces will contain application and framework traces similar to how they are displayed in
HTML error page.
By default, config.debug_exception_response_format is set to :api
so as to render responses in the same format as requests.
If you want the original behavior of rendering HTML pages,
you can configure this option as follows.
We will see how migrations in Rails 5 differ by looking at different
In Rails 4.x command
will generate migration
as shown below.
In Rails 5 the same command
will generate following migration.
Let’s see the generated schema after running migration generated in
Rails 5 added the NOT NULL constraints on the timestamps columns
even though not null constraint was not specified in the migration.
Let’s look at another example.
In Rails 4.x command
would generate following migration.
In Rails 5.0, same command will generate following migration.
There is no mention of index: true in the above migration.
Let’s see the generated schema after running Rails 5 migration.
As you can see, an index on user_id column is added even though it’s not
present in the migration.
Migration API has changed in Rails 5
Rails 5 has changed migration API because of which
even though null: false options is not passed to timestamps
when migrations are run then not null is
automatically added for
Similarly, we want indexes for referenced columns
in almost all cases.
So Rails 5 does not need references to have index: true.
When migrations are run then index is automatically created.
Now let’s assume that an app was created in Rails 4.x. It has a bunch of
migrations. Later the app was upgraded to Rails 5. Now when older
migrations are run then those migrations will behave differently and
will create a different schema file. This is a problem.
Solution is versioned migrations.
Versioned migrations in Rails 5
Let’s look at the migration generated in Rails 5 closely.
In this case CreateUsers class is now inheriting from
Here [5.0] is Rails version that generated this migration.
Solving the issue with older migrations
Whenever Rails 5 runs migrations, it checks the class of the current
migration file being run.
If it’s 5.0, it uses the new migration API which has changes
like automatically adding null: false to timestamps.
But whenever the class of migration file is other than
Rails will use a compatibility layer of migrations API.
compatibility layer is present for Rails 4.2.
What it means is that all migration generated prior to usage of Rails 5
will be treated as if they were generate in Rails 4.2.
You will also see a
asking user to add the version of the migration to the class name for older migrations.
So if you are migrating a Rails 4.2 app, all of your migrations will have class
ActiveRecord::Migration. If you run those migrations in Rails 5, you will see
a warning asking to add version name to the class name so that class name looks like
In Rails 4.2,
Active Job was integrated with Action Mailer
to send emails asynchronously.
Rails provides deliver_later method to enqueue mailer jobs.
Note that the task of delivering email was put in queue called
In Rails 4.x, all background jobs are given queue named “default” except
for mailers. All outgoing mails are given the queue named “mailers” and
we do not have the option of changing this queue name from “mailers” to
Since Rails 4.x comes with minimum of two queues it makes difficult to
use queuing services like que which
relies on applications having only one queue.
Customizing queue name in Rails 5
In Rails 5, we can now
change queue name
for mailer jobs
using following configuration.
To add precision on datetime column
we need to add limit option to it.
By default it is set to 0.
This adds precision(6) to last_seen_at column
in users table.
Rails 4.x behavior
Let’s look at the some of the examples
with different precision values.
The task here is to set end_of_day value
to updated_at column.
With precision set to 6
Everything looks good here.
But let’s look at what happens when precision is set to 0.
With precision set to 0
So far everything looks good here too.
Now let’s see what happens when we reload this object.
As we can clearly see
after the reload
updated_at value has been rounded off from 2016-01-18 23:59:59.999999
to 2016-01-19 00:00:00. It might seem like a small issue but notice
that date has changed from 01/18 to 01/19 because of this rounding.
Improvement in Rails 5
Rails team fixed
by removing fractional part if
mysql adapter does not support precision.