Migrations are versioned in Rails 5
This blog is part of our Rails 5 series.
We will see how migrations in Rails 5 differ by looking at different cases.
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.
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
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
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 deprecation warning 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