How to create Active Record migrations in Ruby on Rails

Updated: 

In Ruby on Rails, migrations are essential for managing changes to your database schema over time. They let you modify your database structure using Ruby code, rather than writing raw SQL. This tutorial will show you commands for creating migration tasks using Active Record, Rails' built-in ORM.

This lesson is from Full Stack Rails Mastery.

Create Table Migration
bin/rails generate migration CreateProducts name:string price:decimal

Migration file:
class CreateProducts < ActiveRecord::Migration[7.2]
  def change
    create_table :products do |t|
      t.string :name
      t.decimal :price

      t.timestamps
    end
  end
end


Add Column Migration
To add a column to an existing table:

bin/rails generate migration AddStockToProducts stock:integer


Migration file:

class AddStockToProducts < ActiveRecord::Migration[7.2]
  def change
    add_column :products, :stock, :integer
  end
end


Remove Column Migration
To remove a column from a table:

bin/rails generate migration RemoveStockFromProducts stock:integer


Migration file:

class RemoveStockFromProducts < ActiveRecord::Migration[7.2]
  def change
    remove_column :products, :stock, :integer
  end
end


Change Column Migration
To change the type or properties of an existing column:

bin/rails generate migration ChangePriceInProducts


Migration file:

class ChangePriceInProducts < ActiveRecord::Migration[7.2]
  def change
    change_column :products, :price, :float
  end
end


Rename Column Migration
To rename an existing column:

bin/rails generate migration RenameNameInProductsToTitle


Migration file:

class RenameNameInProductsToTitle < ActiveRecord::Migration[7.2]
  def change
    rename_column :products, :name, :title
  end
end


Add Index Migration
To add an index to a column:

bin/rails generate migration AddIndexToProductsTitle


Migration file:

class AddIndexToProductsTitle < ActiveRecord::Migration[7.2]
  def change
    add_index :products, :title
  end
end


Remove Index Migration
To remove an index from a column:

bin/rails generate migration RemoveIndexFromProductsTitle


Migration file:

class RemoveIndexFromProductsTitle < ActiveRecord::Migration[7.2]
  def change
    remove_index :products, :title
  end
end


Add Reference Migration
To add a foreign key reference:

bin/rails generate migration AddUserRefToProducts user:references


Migration file:

class AddUserRefToProducts < ActiveRecord::Migration[7.2]
  def change
    add_reference :products, :user, foreign_key: true
  end
end


Remove Reference Migration
To remove a foreign key reference:

bin/rails generate migration RemoveUserRefFromProducts


Migration file:

class RemoveUserRefFromProducts < ActiveRecord::Migration[7.2]
  def change
    remove_reference :products, :user, foreign_key: true
  end
end


Create Join Table Migration
To create a join table for many-to-many relationships:

bin/rails generate migration CreateJoinTableProductsUsers products users


Migration file:

class CreateJoinTableProductsUsers < ActiveRecord::Migration[7.2]
  def change
    create_join_table :products, :users do |t|
      t.index :product_id
      t.index :user_id
    end
  end
end


Change Table Migration
To apply multiple changes to a table:

bin/rails generate migration UpdateProducts


Migration file:

class UpdateProducts < ActiveRecord::Migration[7.2]
  def change
    change_table :products do |t|
      t.string :description
      t.rename :price, :cost
    end
  end
end


Drop Table Migration
To drop an existing table:

bin/rails generate migration DropProducts


Migration file:

class DropProducts < ActiveRecord::Migration[7.2]
  def change
    drop_table :products
  end
end


Drop Join Table Migration
To drop a join table:

bin/rails generate migration DropJoinTableProductsUsers


Migration file:

class DropJoinTableProductsUsers < ActiveRecord::Migration[7.2]
  def change
    drop_join_table :products, :users
  end
end



Create View Migration
Creating views is less common but can be done like this:

bin/rails generate migration CreateActiveUsersView


Migration file:

class CreateActiveUsersView < ActiveRecord::Migration[7.2]
  def up
    execute <<-SQL
      CREATE VIEW active_users AS
      SELECT * FROM users WHERE active = true
    SQL
  end

  def down
    execute <<-SQL
      DROP VIEW active_users
    SQL
  end
end


Rollback Migration
To rollback the most recent migration:

bin/rails db:rollback

Rollback Specific Version
To rollback to a specific version:

bin/rails db:rollback VERSION=20230815123456

Migrate Specific Version
To migrate to a specific version:

bin/rails db:migrate:up VERSION=20230815123456

Migrate Redo
To redo the most recent migration (rollback and then migrate again):

bin/rails db:migrate:redo

Rollback with STEP
To rollback a specific number of steps:

bin/rails db:rollback STEP=4

Migrate with STEP
To migrate a specific number of steps:

bin/rails db:migrate STEP=4

Heroku Migrations
To run any of the above migrations on Heroku, prepend "heroku run" to any of the commands above. For example, for a simple migration:

heroku run rails db:migrate