Rails migration

Generate migration

rails g migration MyVeryFristMigration # g = generate

rails will generate a file in format timestamp_my_very_first_migration.rb

class MyVeryFirstMigration < ActionRecord::Migration[5.0]
  def change
    # your migration code
  end
end

rails is smart enough to understand to run up or down when run migration, for previous version, you can explicit write:

class MyVeryFristMigration < ActionRecord::Migration[5.0]
  def up
    # rails db:migrate or rake db:migration for prev version
  end

  def down
    # rails db:rollback
  end
end

Model generation

migration can be generated by generate a model as well:

rails g model User

then we got at least:

models/User.rb
db/timestamp_user.rb

To create a table, use the following code:

# 20190516100120_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      # t.column :column_name, :data_type, { options }
      t.column :email, :string
      t.string, :user_name # shorthand syntax
    end
  end

  # rollback
  # drop_table :users
end

data types:

  • binary
  • boolean
  • date
  • datetime
  • decimal
  • float
  • integer # int
  • string # nvarchar 225
  • text # text
  • time

options:

:limit     # size
:default   # default value
:null      # true/false

# for decimal/float
:precision # number
:scale     # number

For example:

def change
  create_table :users do |t|
    t.user_name, :string, limit: 50, null: false
    t.email, :string, limit: 50
    t.full_name, :string, default: "Anonymous" # limit: 225
    t.debt, :decimal, precision: 10, scale: 2 # 12345678.91
  end
end

If you want to use another column for identity, then you can turn off the default id:

def change
  create_table users, id: false do |t|
    # nah, you should not
  end
end

Run migration

To run all pending migrations, run:

rails db:migrate # or rake db:migrate for prev version

To rollback latest migration, run:

rails db:rollback

or rollback to specific version:

rails db:rollback VERSION=timestamp

wait, what timestamp? say if you have 20190516100120_create_users.rb then timestamp is 20190516100120

#tips: to rollback to very first version:

rails db:rollback VERSION=0

VERSION has to be uppercased.

Other helpful migrate commands:

  • rails db:migration:status
  • rails db:migration:up VERSION=timestamp
  • rails db:migration:down VERSION=timestamp
  • rails db:migration:redo VERSION=timestamp

Migration (mi) methods

1. Table mi

# create table
create_table(table, options) do |t|
end

# Ex:
create_table :users do |t|
  t.user_name, :string, limit: 50, null: false
end

# drop table
drop_table(table)

# rename table
rename_table(table, new_table_name)

2. Column mi

add_column(table, column, type, options)
# Ex:
add_column :users, :user_type, :integer, default: 0

remove_column(table, column)

rename_column(table, column, new_name)

change_column(table, column, type, option)

3. Index mi

add_index(table, column, options) # should add index for all FKs
# Ex:
add_index :users, :user_contacts

remove_index(table, column)

where index options are:

unique: true/false
name:   "your_custom_index_name"

Fix migration errors

If you have issue when run migration, for example column already exist, you can use rails console to fix it:

ActiveRecord::Migration.remove_column :table_name, :column_name