We are hiring

Rails Migrations in a nutshell

Mohd Sameer Author
September 07, 2020

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 (5)

Shad over 1 year ago

Thanks for saving my time.

Jason almost 2 years ago

Good article. thanks, author.

Alex almost 2 years ago

Very Helpful

Mukarram Malik almost 2 years ago

great

Gajendra Singh about 1 year ago

very helpful

GoodFirms Badge