Trusted answers to developer questions

What are Ruby on Rails Migrations?

Free System Design Interview Course

Many candidates are rejected or down-leveled due to poor performance in their System Design Interview. Stand out in System Design Interviews and get hired in 2024 with this popular free course.

Migrations update the database schema

Migrations in Ruby on Rails allow us to make changes in the database schema in a convenient manner. Rails migrations help keep track of what new changes are made to an application’s database schema, when each change is made, and the order in which the changes are made.

Ruby on Rails is a convention over configuration framework.

Migrations provide lot of benefits, including:

  • When working on a large project with different team members, it gets easier to keep track of all the changes that the schema goes through.

  • Migrations make it easier to rollback to an older schema version, undoing specific migrations.

  • Rails migrations make changes more readable and easier to understand.

  • Each developer will know whenever a schema is updated, and they can use migrations to speed up to the latest version.

Each migration is stored as a separate file in the project’s db/migrate folder. Each migration file consists of a single Ruby class with a certain syntax that makes it easy to understand what new changes are being incorporated to the schema.

Since Ruby on Rails is a convention over configuration framework, the migration setup follows a well-defined path.

Each new migration file is titled in the format YYYYMMDDHHMMSS_create_products.rb.

For instance, if we are generating a migration file from a class named CreateProducts on 2008/09/062008/09/06 at time 12:00:0112:00:01, the file name would be 20080906120001_create_products.rb.

The first part of each migration file’s title is a timestamp that tells us when the migration file was generated. This is helpful because it lays out a chronological timeline of changes to the schema.

Rails automatically creates a timestamp whenever a user creates a migration file. The second part of migration file’s title depicts what the purpose of the migration is. This is also inferred by rails based on the command the user entered into the terminal to generate that file.

How to create a migration

We can create a migration file using the following command:

rails g migration AddPriceToProduct type:string

The AddPriceToProduct statement in the command will tell Rails that the migration is meant to add a new column to the products table. If we entered a command that began with Create or Remove instead of Add, Rails would identify that those migrations were meant to either create a table or remove a column from a table. Therefore, we need to follow a particular convention when entering a command to generate a migration.

The term g in the command shown above is a short alternative for generate. These two terms can be used interchangeably. Therefore, the command, rails generate migration AddPriceToProduct type:string would also produce the same result.

The command above will create a file similar to the one shown below:

class AddPriceToProduct < ActiveRecord::Migration
def change
add_column :products, :price, :float
end
end

The migration file will consist of a Ruby class whose name is derived from the command entered to generate migration. Rails not only obtains the class name, but also deciphers what type of migration the user intended to create. As a result, the class is already populated with the relevant code used to add a new column to the the products table. It also infers that the new column will store data of type float.

Similarly, if we entered the command given below, Rails would infer that the user intends to remove a column but, instead of the add_column keyword, it will use the remove_column keyword.

rails generate migration RemovePriceFromProducts price:float

The command will proceed to generate a migration file as shown below:

class RemovePriceFromProduct < ActiveRecord::Migration
def change
remove_column :products, :price, :float
end
end

The Active Record in Rails keeps track of which migrations have been executed. Once you are done creating a migration file, you only need to enter the following command:

rails db:migrate

This command will execute all the migration files that have not yet been executed. Active Record also keeps track of which migrations are still pending. With the execution of each migration file, the db/schema.rb filecontains the overall details of the structure of the current database schema is also updated.

You can create migrations to add, remove, and update columns, and also create or drop tables. You can also rollback migrations that have already been executed. Rails provides a very versatile functionality to manage and update the project’s schema using migrations.

Rolling back migrations

In case a migration has been executed and is now a part of the application’s database schema, it can always be rolled back or reverted to a state prior to when that particular migration altered the schema.

rails db:rollback STEP=1

The command shown above will undo the most recently executed migration. The STEP=1 portion of the command makes sure that only the most recent migration needs to be rolled back. In case we want more than one migration to be rolled back, we can change the number of the STEP flag. For example, STEP=3 would roll back the three most recent executed migrations.

A limitation of this command is that no out-of-order migration file can be rolled back, and only migrations that occurred in a sequence can be handled (we get to specify up to what point using the STEP flag).

In case an out-of-order migration has to be reverted, which would mean no migration before or after it would be affected, we can use the following command:

rails db:migrate:down VERSION=20100905201547

The VERSION flag is used as an identifier for the migration that needs to be rolled back. The number, which is always the first part of the title of each migration file, represents the timestamp of the migration.

Example

A simple rails application is shown below. You can use this application to test out the commands discussed in this shot. Follow the given guidelines to interact with the application:

  1. Click the RUN button below and wait for the application to start.
  2. Once the simple UI appears in the output tab, feel free to test it out and see how the application functions. You should be able to create product objects using the create product form.
The output should appear as shown in this image.
  1. Switch over to the terminal tab and enter Ctrl + c to stop the application and use the terminal yourself.
  2. Try rolling back the most recent migration using the command.
rails db:rollback STEP=1
  1. Restart the server once again using the command below:
rails s -b 'ssl://0.0.0.0:3000?key=localhost.key&cert=localhost.crt'

If everything worked fine, the price column in the UI should disappear. This is because an if condition has been added to the page that only shows the price column at the frontend if the Product model contains a price column.

Please note you should be in the /myapp/test_proj directory in the terminal for the commands to work.

And that’s it! You can try adding in different commands in the widget given below as well.

//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css

RELATED TAGS

ruby
Did you find this helpful?