Rails DB Migration Cheatsheet


Jan 16th 2024: Added UUID column for Postgres

Add/Remove/Modify columns

Column data types

# Standard
:binary
:boolean
:date
:datetime
:decimal
:float
:integer
:bigint
:primary_key
:references
:string
:text
:time
:timestamp

# Extra native data types for Postgres:
:hstore
:json / :jsonb
:array
:cidr_address
:ip_address
:mac_address

# and more
# @see http://stackoverflow.com/q/17918117

Change existing table

add_column :products, :price, :decimal, precision: 5, scale: 2
change_column :products, :quantity, :integer
# change column type from string to integer with Postgres
change_column :products, :price, 'integer USING CAST(price AS integer)'
remove_column :products, :photo, :string
rename_column :products, :image, :photo
change_column_default :advertisements, :enable, from: true, to: false
drop_table :products

Apply bulk: true when changing multiple columns in an existing table

# before
def up
  add_column :table, :useful_foreign_key, :integer
  add_index  :table, :useful_foreign_key
  add_column :table, :summary, :string
end

# after
def up
  change_table :table, bulk: true do |t|
    t.integer :useful_foreign_key
    t.index   :useful_foreign_key
    t.string  :summary
  end
end

Indexes

add_index :products, :category_id
add_index :users, :email, unique: true
# partial index with Postgres
add_index :users, :is_active, where: "is_active = true"

remove_index :products, :category_id

Migrate and Rollback

# Rails 3/4
rake db:migrate
rake db:rollback

# Rails 5+
rails db:migrate
rails db:rollback

# migrate/rollback a specific version
rails db:migrate VERSION=version
rails db:rollback VERSION=version

# rollback several migrations
rails db:rollback STEP=3

# rollback and rerun migrations
rails db:migrate:redo STEP=3

Misc

Reset PK sequence for Postgres:

# single table
ActiveRecord::Base.connection.reset_pk_sequence!(table_name)

# all tables
ActiveRecord::Base.connection.tables.each do |t|
  ActiveRecord::Base.connection.reset_pk_sequence!(t)
end

Change DB system, for example from sqlite to postgres, avaiable since Rails 6:

# pass --force to skip prompt
rails db:system:change --to=postgresql

Add uuid column (Postgres) with auto generated UUID:

# Enable pgcrypto extension if it is not enabled yet
class EnablePgcrypto < ActiveRecord::Migration[7.1]
  def up
    enable_extension 'pgcrypto'
  end

  def down
    disable_extension 'pgcrypto'
  end
end

# Add uuid column
class AddUuidToUsers < ActiveRecord::Migration[7.1]
  def change
    add_column :users, :uuid, :uuid, default: "gen_random_uuid()", null: false
  end
end