Understanding Ruby on Rails Migrations

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.

The purpose of 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.

What are the benefits of using Migrations?

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.

What do Migration files look like?

Last week we ran the Rails generator to create a new Article Model.

bin/rails g model Article title:string body:text  
[/bash]

As part of this generation process, Rails also created a migration file:  
```ruby  
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.

Understanding the Migration file

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.

Creating Migration files

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  
[/bash]

This should create the following migration file  
```ruby  
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  
[/bash]

This will create the following migration file:  
```ruby  
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  
[/bash]

This would generate the following migration:  
```ruby  
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  
[/bash]

Running the command above would generate the following migration:  
```ruby  
class CreateComments < ActiveRecord::Migration  
def change  
create_table :comments do |t|  
t.string :name  
t.text :comment  
end  
end  
end  

Running Migrations

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  
[/bash]

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.


## Rolling back migrations

If you have made a mistake and you want to roll back the previous migration you can do so using the following command:  
```bash  
bin/rake db:rollback  
[/bash]

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:  
```bash  
bin/rake db:rollback STEP=2  
[/bash]

This will rollback through the previous 2 migrations.


## Conclusion

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!


Understanding Ruby on Rails Migrations
Share this