Oct 07, 2015
Table of contents:
Last week we looked at creating our first Ruby on Rails Model.
Rails Models are backed by a database table. So for example, if you had an Article
Model you would also need an articles
database table.
In order to control our database schema and to make deployment and changes easier we can use migration files.
A migration file is a set of instructions that will be run against your database.
This means if you need to make a change to your database, you can capture that change within a migration file so it can be repeated by other installations of your project.
This will be extremely useful when it comes to deploying your application or working with other developers.
In today’s tutorial we will be taking a look at Rails migrations.
In order to fully understand migrations and why you need them, first it’s important to understand their purpose.
The majority of all web applications will need a database. A database is used for storing the data of the web application. So for example, that might be blog posts or your user’s details.
The database is made up of tables that store your data. Typically you would run SQL statements to create or modify the tables and columns of a database.
Rails introduces a specific Domain-specific language for writing instructions for how a database should be created. This saves you from writing SQL statements.
A migration is a file that contains a specific set of instructions for the database. For example, last week we created a migration file to create the articles
table with columns for title
and body
.
When this migration file is run, Rails will be able to make the changes to the database and automatically create the table for us.
Over time as the database evolves, the migration files will act as a versioned history of how the database has changed. This means you will be able to recreate the database from the set of instruction files.
There are a number of benefits to using Migrations as part of your Rails project.
Firstly, your application is going to be pretty useless without a database. When someone grabs a copy of the code they need to set up a local version of the database. Instead of passing around a file of SQL statements, the Rails project will automatically have everything it needs to recreate the database.
Secondly, when working with other developers, you will likely face a situation where one developer needs to modify the database in order to implement the feature she is working on. When that developer pushes her code and you pull down the changes, your application will be broke without also modifying the database. The migration file will be able to automatically make the change so you don’t have to try and reverse engineer what has changed.
And thirdly, when you deploy your application to a production server you need a way for the production database to be created or updated. Updating anything in production manually can be a bit hairy as any human error can potentially be disastrous. By using database migrations we can completely remove the human element of updating a production database.
Last week we ran the Rails generator to create a new Article
Model.
bin/rails g model Article title:string body:text
As part of this generation process, Rails also created a migration file:
class CreateArticles < ActiveRecord::Migration
def change
create_table :articles do |t|
t.string :title
t.text :body
t.timestamps null: false
end
end
end
This migration will create a new database table called articles
. We’ve also specified that the table should have a title
column of type string
and a body
column of type text
.
Rails will also add a primary key column of id
as well as created_at
and updated_at
timestamps by default.
The migration file is essentially just a regular Ruby class that is run during the migration process:
class CreateArticles < ActiveRecord::Migration
end
The CreateArticles
class inherits from the ActiveRecord::Migration
class.
In the change
method we have the instructions of what the migration should do:
def change
create_table :articles do |t|
t.string :title
t.text :body
t.timestamps null: false
end
end
In this example we are calling the create_table
method with an argument of :articles
for the table name.
We also pass a block to the method that allows us to specify the names and types of the columns.
In the previous example we saw how we can automatically generate a migration file using the model generator command.
However, you will need to generate a migration file whenever you want to alter an existing table or create a join table between two tables.
So how do you generate a standalone migration file?
Rails provides a migration generator command that looks something like this:
bin/rails g migration AddSlugToArticles
This should create the following migration file:
class AddSlugToArticles < ActiveRecord::Migration
def change; end
end
You can also add the columns you want to add to the table to the generator command:
bin/rails g migration AddSlugToArticles slug:string
This will create the following migration file:
class AddSlugToArticles < ActiveRecord::Migration
def change
add_column :articles, :slug, :string
end
end
As you can see in this example, we are calling the add_column
method and passing the table name :articles
, the column name :slug
and the type :string
.
The migration will automatically created with the add_column
method if your migration begins with Add
.
If you wanted to remove a column from a table, you would generate a migration that begins with Remove
:
bin/rails g migration RemoveSlugFromArticles slug:string
This would generate the following migration:
class RemoveSlugFromArticles < ActiveRecord::Migration
def change
remove_column :articles, :slug, :string
end
end
If you would like to create a new table you should run a generator command where the migration begins with Create
. For example:
bin/rails g migration CreateComments name:string comment:text
Running the command above would generate the following migration:
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :name
t.text :comment
end
end
end
Once you have generated your migration files and you are happy with the structure of the tables that you have defined, it’s time to run the migrations to update the database.
To run the migration files you can use the following command:
bin/rake db:migrate
This will work through each of your migration files in the order of which they were generated and perform that action on the database. If everything goes smoothly you should see the output from the command console telling you which migrations were run.
If you try to run the db:migrate
command again you will notice that nothing will happen.
Rails keeps track of which migrations have already been run. When you run the db:migrate
command, Rails will only run the migrations that have yet to be run.
If you have made a mistake and you want to roll back the previous migration you can do so using the following command:
bin/rake db:rollback
For simple migrations Rails can automatically revert the changes from the change
method.
If you need to rollback through multiple migrations you can add the STEP
parameter to the command:
bin/rake db:rollback STEP=2
This will rollback through the previous 2 migrations.
Migrations are an important part of a modern web application framework. Nearly all web applications have a database, and so it’s pretty important that you have the right tooling.
Migrations make it easy to create database tables. You will no longer have to remember the syntax for creating tables or defining column.
If you were to switch databases, you will also find that the migrations are agnostic to the type of database you are using.
However, really the biggest benefit of migrations is how easy it is to create a new database, or modify an existing one. When working on a team of developers this is going to be essential!