Rails Migrations in a nutshell

Screenshot 2020 09 07 at 7.36.40 pm
Mohd Sameer Author
September 07, 2020
Migration thumb

Migrations are the perfect way for you to create and modify your database in an organized and in a well-structured manner. One of the main advantages of migrations is that we don’t have to write SQL queries since migrations provide you an easy Ruby DSL to Create/Change your table. 

Migrations allow us to create tables, add or remove columns, and add indexes on columns. Whenever a migration is generated through command it is stored in db/migrate folder of your Rails app directory. 

In this post, you'll be learning about the following point of migrations


Creating a table through migrations

This how a table is created using migrations. Through the following command, we are generating a Post table within our database with two columns Title and Content. 

Remember to use the capitalized name for the table/model name.

 

$ rails g migration CreatePost title:string content:text

 

This can also be done as 

 

$ rails g model Post title:string content:text


Both commands would generate the same file with a title consisting of timestamped and class name following by the ruby extension. 20200715064057_create_posts.rb 

class CreatePosts < ActiveRecord::Migration[5.1]
  def change
  create_table :posts do |t|
    t.string :title
    t.text :conent
 
      t.timestamps
    end
  end
end

 

The next step is to run

rails db:migrate

 

Upon running rails db:migrate   a table called posts with a string column called title and a text column called content would be added to db/schema.rb. An integer column called id
and a column timestampd will also be added implicitly, id is the default primary key for all Active Record models and  timestamp adds two columns, created_at and updated_at to the database schema. These two columns are automatically managed by ActiveRecord if their record exists.

*Note - Running rails db:migrate   is mandatory every time a rails migration is added

 

Usage of ‘text’ or ‘string’  while generating migrations?

As a general rule of thumb, use :string for short text input (username, email, password, titles, etc.) and use :text for longer expected input such as descriptions, comment content, etc.

 

Migration to create a table with reference columns

The need for creating a table like this arises when multiple records in a table are associated with multiple records in another table. For example, there's a Post table and a Tag table. Both tables can have multiple records associated with each other so we need to have a bridge table, PostTag.

$ rails g migration CreatePostTag post:references tag:references

 

This will generate the following code in a migration file

class CreatePostTags < ActiveRecord::Migration[5.1]
  def change
    create_table :post_tags do |t|
      t.references :post, foreign_key: true
      t.references :tag, foreign_key: true

      t.timestamps
    end
  end
end

When we reference a model, index on the foreign_key is automatically created.


Changing table through migrations

Rename a table with a single Rails migration

I have a Post table within my database but for reason, I want to change it to Article. Here how you can do it; 

We need to generate a migration through the following command

$ rails generate migration RenamePostToArticle

 

 

This will give us an empty migration file, we can modify it ourselves with the following code


class RenameOldTableToNewTable < ActiveRecord::Migration[5.1]
def change
rename_table :posts, :articles #Tables name should be pluralized
end
end


Run rails db:migrate and you are good to go😎

 

Let's learn to drop a table from the database.

Through this command, we are generating a migration to remove the Post table including its columns from the database.

$ rails generate migration DropPostTable

 

The above command would generate an empty migration file, we can edit it with the following code;

 

class DropPostsTable < ActiveRecord::Migration[5.1]
def up
drop_table :posts
end


def down
raise ActiveRecord::IrreversibleMigration
end
end


Run rails db:migrate to disappear the Post table from your database.

Rollback a migration

Running plain rails db:rollback command would revert the lastest migration changes to the database.

But if you want to revert a specific migration you can do it with the following command.

 

$ rake db:migrate:down VERSION=20200715064057

 

This will revert the following migration file: db\migrate\20200715064057_create_posts.rb  Here migration file is identified by its timestamp.

another way of rollback a migration is to use the STEP argument with rails db:rollback command. 

Here is how you can execute this;

$ rake db:rollback STEP=2


In this case, we are defining the number of migration files we want to roll back in a chronological manner.

 

Command to Add a column to an existing table

We sometimes need to add more columns to our table for our development requirements. The most efficient way of adding a column is to generate a migration. 

We need to add a publish column to our existing Post table. We can do by running the following command;

 

$ rails g migration AddPublishToPost publish:boolean

 

It would give us the following code in the migration file

 

class AddPublishToPost < ActiveRecord::Migration[5.1]
  def change
    add_column :posts, :publish, :boolean
  end
end


Assigning default value to a column

We can assign a default value to a column by modifying the above file with the following code.

class AddPublishToPost < ActiveRecord::Migration[5.1]
  def change
  add_column :posts, :publish, :boolean, default: false
  end
end

 

We just added a default: false  key-value pair to make the publish always default upon initializing a new record.


A good way to Rename a column.

Let's change the Post publish  column to status. To make this change we need to have the following migration generated.

$ rails g migration ChangePublishToStatus


This will give us a migration file with an empty change method. We need to modify the migration file like this;

class ChangePublishToStatus < ActiveRecord::Migration[5.1]
  def change
 rename_column :posts, :publish, :status
  end
end

It will rename the column but keeps the type and content remains the same.

 

Change Column

Let's learn to change a column type in the most simple and reliable way. In this example, I want to change the publish  column type from boolean to integer  

Run the following command to generate a migration.

rails g migration ChangePostPublish


Edit it like the following file;

class ChangePostPublish < ActiveRecord::Migration[5.1]
  def change
   reversible do |dir|
    change_table :posts do |t|
      dir.up   { t.change :publish, :integer}
      dir.down { t.change :publish, :boolean }
      end
    end
  end
end

It will change the column type.


Remove a Column from table

Here how you can remove the column from a table. Let's take an example of Post table, we want to remove the view column from it. 

Create a migration using the following command

rails g migration RemoveViewFromPost view:integer

 

It will generate a migration file with the following code. we don't need to modify it.

class RemoveViewFromPost < ActiveRecord::Migration[5.1]
  def change
  remove_column :posts, :view, :integer
  end
end


Running rails db:migrate would extract and remove the view column from the Post table.




Reset database

$ rake db:reset db:migrate

 

$ rake db:drop db:create db:migrate

Seeding databases


Run rails db:seed to create a record of Post using seed.

Creating multiple records with single rails db:seed command.

iterate over the Post using Ruby Times Loop. Our db/seed.rb file would look like this;


You can also run the seed command to populate the database at the time of creating a database.

$ db:create db:migrate db:seed



Please share this article if you found this useful. I would write more such articles for you to simplify your rails learning.



Tags



Comments (3)

Av 8
Jason 15 days ago

Good article. thanks, author.

Av 9
Mukarram Malik 15 days ago

great

Av 0
Alex 15 days ago

Very Helpful