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
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
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
Rails will also add a primary key column of
id as well as
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
CreateArticles class inherits from 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
The migration will automatically created with the
add_column method if your migration begins with
If you wanted to remove a column from a table, you would generate a migration that begins with
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
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!