Working with Migrations in Rails

Ruby. Rails. ActiveRecord. These are all things that you will come to know like the back of your hand, things that you will be exposed to in greater and greater frequency as you dive deeper into the world of Ruby. Today we are going to take a closer look at migrations, what they are and how to use them.

What are Migrations?

Let’s start simple – What are migrations? Migrations allow for you to use Ruby to alter your database schema. If you don’t already know what a schema is, let’s take a look at the definition:

Schema – A representation of a plan or theory in the form of an outline or model.

Now let’s apply that to what we know of databases. In this sense, a schema is a representation of how our database is structured in the Ruby language. Here is an example of a schema from one of my projects:

schema.png

You will see that at the top we have a table called, reviews and inside of this table we have columns for title, cost, etc with each column being specified as to the type of data it is storing: string, integer etc.

So to back up and give a larger view of what migrations are, they allow us to more easily alter our database, especially so with larger teams. If one person on a team would like to add a table for users they can do so with a migration (rails g migration create_users) and when the other team members want the new version, they simple pull down from the repo and run rake db:migrate and now the scheme and database are updated.

Using Migrations

Now that we have a pretty good feel for what migrations are let’s take a look at ways in which we can use them. Here is a list of different types of migrations you can use to alter your rails database:

  • add_column
  • change_column 
  • change_table
  • create_table
  • drop_table
  • remove_column
  • rename_column

You are likely to use the majority of these commands with great frequency as you build out your projects. When you are first starting your database, you will initialize it with a rake db:create command and then you can use your migrations for different actions.

It is important to note that these commands (e.g add_columnrename_column) are only run inside of migrations which exist in your /db/migrate folder.

In order to initiate a migration, you must follow the Rails convention which is as follows: rails g migration descriptive_name_for_this_migration. The g is shorthand for generate, either one can be used – it is a matter of personal preference. Secondly, the name of the migration should reflect what it is you are looking to do. For instance, if you have a table, users and would like to create a migration that adds a column, location, to that table, your migration would look something like this: rails g migration add_location_to_users_table. This way, when other team members look at the migrations, they are able to know immediately what migration is responsible for what.

Now that we have created a migration, let’s give it the stuff it needs to get the job done. Take a look at this example below:

venues.png

This migration is the product of running the command, rails g migration create_venues. This in turn creates a blank ruby class, CreateVenues with a change method, def change. It is up to the programmer to tell the database what this migration will actually do. In this case, we want to create a table for venues and inside of that table, we want some columns, which are outlined above for name, url etc…

You will notice that this is all happening inside of a loop. This is because, the loop looks to the migration command, create_table and then to the name of that table, venues and then it iterates through in order to create each column that you specify.

The syntax for columns here is simple, you do t. then the type of data this column will hold, it could be string, integer or boolean to name a few. Then, the name of the column itself in the form of a symbol, e.g :name. If this field MUST be filled out you will put null: false, which essentially says, this field cannot be blank – it is a form of validation, we can further validate on the model level as well. Then, we cap it off with t.timestamps null: false this will provide timestamps for all new records in this column. We are now done with our migration!

In order to update our database to have this new table, we go back to our terminal and run the following command: rake db:migrate. This will run through our /db/migrate folder and find all migrations and then run them based on what code we put in each of them. In the case, as above, running rake db:migrate will create a new table, venues with a number of different columns.

In order for you to persist this type of data to the database, you will need to make a corresponding Model to represent this table. If you are shaky on how the Model works in rails please refer to my post on the MVC – Model, View & Controller for a deeper breakdown.

Adjusting Migrations

Let’s say you ran your migrations and noticed that something was wrong. Maybe a column name was incorrect or the data type was wrong, maybe you just want to simply add or delete a column on a table. How do you do it?

There are two quick ways to do this. The first can be used when your projects are small and in their infancy in terms of development and the second is more of a best practices approach that should be used whenever possible.

The First Approach

You only have a few tables in your database and you just started this project. You don’t anticipate anyone else jumping on to do any collaborating, so what they hell – Rollback. The command, rake db:rollback will do just that, rollback any database changes that were made based on migrations in your /db/migrate folder.

In a sense, it reverts back to your last ‘checkpoint’ or ‘save’. Now, once the rollback is successfully completed, you can go into the migration that you want to change and simply delete, add or otherwise modify the migration to be how you want it. If you want to change a data type from t.string to t.integer – go for it. Then save the file, head back to your terminal and run rake db:migrate. Go ahead and checkout your schema and you will see the new changes are reflected in the database.

This is a quick way of altering things in your database, but I do not recommend it. Why? When you begin working on larger and larger projects, you will not be afforded the opportunity to rollback like that, as it may cause other pieces of your code to break. Instead, use the built in commands from activerecord to get those changes in through new migrations.

The Second Approach

With this approach, you are keeping the old migration (as wrong as it may be) and creating a new migration to alter it. This is how you do it. For the sake of example, you want to change add a column from venues – let’s say capacity. You do this: rails g migration add_capacity_column_to_reviews_table. This will then create a new migration for you.

Inside of this migration you need to specify a few things, the first will be the table and the second, the name of the column to add and the third, the datatype of that column. It will look something like this: add_column :venues, :capacity, :integer. This will add the column capacity to the table, venues, once you run rake db:migrate.

Again, this is the preferred method because it gives a clear path of thinking that anyone else can see in your file tree. They will see that you started with a migration to create venues and then later decided to add capacity to that table with another migration. The benefits of using Ruby are largely because of its readability and ease of use – so use that to its greatest potential!

Resources:

Submit a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s