rails db:migrate の使い方|マイグレーション作成・実行・ロールバックを徹底解説

rails db:migrate の使い方|マイグレーション作成・実行・ロールバックを徹底解説

Rails 開発でDBスキーマを変更する際に必須となる マイグレーション(migration)

bin/rails db:migrate

このコマンド1つで、DBのスキーマを安全にバージョン管理しながら変更できる仕組みは、Rails が他のフレームワークと一線を画す強みです。

しかし、実務で使い始めると:

  • マイグレーションファイルはどう作る?
  • changeup/down の使い分けは?
  • ロールバック不可能なマイグレーションは?
  • インデックスや外部キーはどう書く?
  • 巨大テーブルに NOT NULL を追加すると本番が止まる…
  • マルチDB環境での migrate コマンドは?
  • ロールバックが効かないマイグレーションって?
  • どのコマンドを使えば良いか覚えられない

など、知っておくべきことが多くあります。

本記事では、rails db:migrate の使い方を、リファレンスとして実用的に整理します。マイグレーション作成、change/up/down、カラム型・インデックス・外部キー、ロールバック、マルチDB対応、Zero-downtime migration、strong_migrations 活用、ありがちなミス、FAQまで完全網羅。この1本をブックマークすれば、Rails のスキーマ管理を自信を持って実践できるようになります。


目次

結論:今すぐ使える基本パターン10選

時間がない方向けに、超頻出パターンを先に示します。

# ① マイグレーション作成(カラム追加)
bin/rails g migration AddEmailToUsers email:string

# ② テーブル作成
bin/rails g model Post title:string body:text user:references

# ③ マイグレーション実行
bin/rails db:migrate

# ④ 状態確認
bin/rails db:migrate:status

# ⑤ ロールバック(1つ)
bin/rails db:rollback

# ⑥ 複数ロールバック
bin/rails db:rollback STEP=3

# ⑦ 特定バージョンまで
bin/rails db:migrate VERSION=20260601000001

# ⑧ ダウン→アップ(再実行)
bin/rails db:migrate:redo

# ⑨ DBリセット(drop → create → migrate → seed)
bin/rails db:reset

# ⑩ test DB の準備
bin/rails db:test:prepare

詳細は以下で順に解説します。


マイグレーションの基本構造

マイグレーションファイルの命名規則

db/migrate/YYYYMMDDHHMMSS_class_name.rb
                      ↑
              UTCタイムスタンプ

例:

db/migrate/20260620100000_create_users.rb     → class CreateUsers
db/migrate/20260620100100_add_email_to_users.rb → class AddEmailToUsers

タイムスタンプ部分は マイグレーションの順序を決定するキー。

最小のマイグレーションファイル

class AddEmailToUsers < ActiveRecord::Migration[8.0]
  def change
    add_column :users, :email, :string
  end
end
要素説明
ActiveRecord::Migration[8.0]Rails 8.0 マイグレーションAPI
change変更内容を記述するメソッド
add_columnカラム追加のDSL

schema_migrations テーブル

Rails は実行済みマイグレーションを内部的に管理:

SELECT version FROM schema_migrations ORDER BY version;
-- 20260620100000
-- 20260620100100
-- ...

これにより同じマイグレーションが二重実行されないようになっています。


マイグレーションファイルの作成

rails generate migration

最も基本的な作成方法:

bin/rails g migration MigrationName
# 短縮: bin/rails g migration MigrationName

db/migrate/20260620100000_migration_name.rb が生成されます。

カラム追加の慣用パターン

bin/rails g migration AddEmailToUsers email:string

→ 自動的にこう生成:

class AddEmailToUsers < ActiveRecord::Migration[8.0]
  def change
    add_column :users, :email, :string
  end
end

命名規則 Add{Columns}To{Table} でRails が自動推測してくれます。

カラム削除の慣用パターン

bin/rails g migration RemoveEmailFromUsers email:string

class RemoveEmailFromUsers < ActiveRecord::Migration[8.0]
  def change
    remove_column :users, :email, :string
  end
end

Remove{Columns}From{Table} パターン。

テーブル作成

bin/rails g model Post title:string body:text user:references

または:

bin/rails g migration CreatePosts title:string body:text

class CreatePosts < ActiveRecord::Migration[8.0]
  def change
    create_table :posts do |t|
      t.string :title
      t.text :body
      t.references :user, null: false, foreign_key: true
      
      t.timestamps
    end
  end
end

複数カラムを一気に追加

bin/rails g migration AddDetailsToUsers name:string age:integer bio:text

インデックス付きで追加

bin/rails g migration AddEmailToUsers email:string:index

class AddEmailToUsers < ActiveRecord::Migration[8.0]
  def change
    add_column :users, :email, :string
    add_index :users, :email
  end
end

ユニークインデックス

bin/rails g migration AddEmailToUsers email:string:uniq

class AddEmailToUsers < ActiveRecord::Migration[8.0]
  def change
    add_column :users, :email, :string
    add_index :users, :email, unique: true
  end
end

空のマイグレーション

bin/rails g migration UpdateUserStatus

特定パターンに当てはまらない複雑な変更は、空ファイル生成後に手動で記述。


change メソッドの基本

概要

changeマイグレーションの「アップ」処理を記述するメソッド。down(ロールバック)が自動的に推測されます。

class AddEmailToUsers < ActiveRecord::Migration[8.0]
  def change
    add_column :users, :email, :string
    # ↑ ロールバック時は自動的に remove_column が実行される
  end
end

change で自動的にロールバック可能なメソッド

メソッドロールバック動作
add_columnremove_column
add_foreign_keyremove_foreign_key
add_indexremove_index
add_referenceremove_reference
add_timestampsremove_timestamps
change_column_default:from:to必須)元に戻す
change_column_null元に戻す
create_join_tabledrop_join_table
create_tabledrop_table
disable_extensionenable_extension
drop_join_table(block必須)create_join_table
drop_table(block必須)create_table
enable_extensiondisable_extension
remove_column(type必須)add_column
remove_foreign_key(to_table必須)add_foreign_key
remove_indexadd_index
remove_referenceadd_reference
remove_timestampsadd_timestamps
rename_column元の名前に戻す
rename_index元の名前に戻す
rename_table元の名前に戻す

change で動かないパターン

# ❌ remove_column の type省略はロールバック不可
def change
  remove_column :users, :email   # ロールバック時の型情報なし
end

# ✅ 型を指定すればOK
def change
  remove_column :users, :email, :string
end
# ❌ change_column はロールバック不可能(元の型が分からない)
def change
  change_column :users, :name, :text   # 元は何だったか不明
end

# ✅ up/down を分ける
def up
  change_column :users, :name, :text
end

def down
  change_column :users, :name, :string
end

up / down メソッド(複雑な場合)

ロールバックを明示的に制御したい場合は change の代わりに up / down:

class ComplexMigration < ActiveRecord::Migration[8.0]
  def up
    # フォワード処理
    add_column :users, :status, :integer, default: 0
    User.update_all(status: 1)
  end
  
  def down
    # ロールバック処理
    remove_column :users, :status
  end
end

IrreversibleMigration

データ変換でロールバック不可能な場合:

class RemoveEmptyTags < ActiveRecord::Migration[8.0]
  def up
    Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
  end
  
  def down
    raise ActiveRecord::IrreversibleMigration, "Can't recover deleted tags"
  end
end

ロールバック時には明示的にエラーを上げる。

reversible ブロック

change 内で部分的に up/down を分ける場合:

class UpdateUserStatus < ActiveRecord::Migration[8.0]
  def change
    reversible do |dir|
      dir.up do
        execute "UPDATE users SET status = 1 WHERE active = true"
      end
      dir.down do
        execute "UPDATE users SET active = (status = 1)"
      end
    end
  end
end

カラム型一覧

Rails が標準でサポートする型:

用途DB対応
:string短文字列(255文字)VARCHAR
:text長文字列TEXT
:integer整数INT
:bigint大整数(64bit)BIGINT
:float浮動小数点FLOAT
:decimal精密小数(精度指定)DECIMAL
:numericdecimalのエイリアスNUMERIC
:datetime日時TIMESTAMP / DATETIME
:timestamp日時(datetime同等)TIMESTAMP
:time時刻TIME
:date日付DATE
:binaryバイナリBLOB / BYTEA
:boolean真偽値BOOLEAN / TINYINT
:jsonJSONJSON
:jsonbJSONB(PostgreSQL)JSONB
:uuidUUIDUUID
:references関連(外部キー)INTEGER + foreign_key

型オプション

add_column :products, :price, :decimal, precision: 10, scale: 2
add_column :users, :role, :integer, default: 0, null: false
add_column :articles, :tags, :string, array: true, default: []  # PostgreSQL専用
add_column :records, :metadata, :jsonb, default: {}             # PostgreSQL専用

テーブル作成(create_table)

基本

create_table :products do |t|
  t.string :name
  t.text :description
  t.decimal :price, precision: 10, scale: 2
  t.boolean :active, default: true
  t.references :user, null: false, foreign_key: true
  
  t.timestamps  # created_at, updated_at
end

主キー指定

# id を別の型にする
create_table :products, id: :uuid do |t|
  t.string :name
end

# id を作らない
create_table :join_table, id: false do |t|
  t.integer :user_id
  t.integer :role_id
end

# 主キーを変える
create_table :products, primary_key: :sku do |t|
  t.string :sku
  t.string :name
end

関連(references)

create_table :posts do |t|
  t.references :user, foreign_key: true, null: false
  # 自動的に:
  # - user_id カラム作成
  # - インデックス作成
  # - 外部キー制約
end

ポリモーフィック関連

create_table :comments do |t|
  t.references :commentable, polymorphic: true, null: false
  # commentable_id, commentable_type の2カラム作成
end

Self-referential

create_table :employees do |t|
  t.string :name
  t.references :manager, foreign_key: { to_table: :employees }
end

join table(多対多)

create_join_table :users, :roles do |t|
  t.index [:user_id, :role_id]
end
# user_id, role_id の2カラムのみ作成

カラム操作

add_column(追加)

add_column :users, :email, :string
add_column :users, :age, :integer, default: 0, null: false
add_column :users, :status, :integer, default: 0, index: true

remove_column(削除)

remove_column :users, :email, :string
# 型を指定するとロールバック可能

# 複数同時に削除
remove_columns :users, :email, :phone
# ⚠️ Rails 8 ではこの形式の change での自動リバーシブルは限定的

rename_column(リネーム)

rename_column :users, :email, :email_address

change_column(型変更)

change_column :users, :name, :text
change_column :users, :age, :integer, limit: 8   # bigint化

⚠️ change メソッド内では使えない(ロールバック不可)。up/down を分けるか reversible で対応。

change_column_default(デフォルト変更)

# change で使える書き方
change_column_default :users, :status, from: 0, to: 1

change_column_null(NULL制約変更)

change_column_null :users, :email, false  # NOT NULL にする
change_column_null :users, :email, true   # NULL 許可

⚠️ 既にデータがあり、NOT NULLにできない場合は事前にデータをクリーン化する必要あり。


インデックス

基本

# 単一カラム
add_index :users, :email

# ユニーク
add_index :users, :email, unique: true

# 複合
add_index :posts, [:user_id, :created_at]

# 名前指定
add_index :users, :email, name: "index_users_on_email_unique", unique: true

# 部分インデックス(PostgreSQL)
add_index :users, :email, where: "active = true"

# 関数インデックス
add_index :users, "lower(email)", name: "index_users_on_lower_email"

コンカレント追加(PostgreSQL)

巨大テーブルへのインデックス追加でテーブルロックを避ける:

class AddIndexToUsersEmail < ActiveRecord::Migration[8.0]
  disable_ddl_transaction!  # ← 必須
  
  def change
    add_index :users, :email, algorithm: :concurrently
  end
end

disable_ddl_transaction! でトランザクション無効化。algorithm: :concurrently でブロッキングを最小化。

インデックス削除

remove_index :users, :email
remove_index :users, name: "index_users_on_email_unique"

外部キー制約

add_foreign_key

add_foreign_key :posts, :users
# posts.user_id → users.id

# カラム名指定
add_foreign_key :posts, :users, column: :author_id

# 削除動作
add_foreign_key :posts, :users, on_delete: :cascade
add_foreign_key :posts, :users, on_delete: :nullify
add_foreign_key :posts, :users, on_delete: :restrict

references で同時作成

add_reference :posts, :user, foreign_key: true, null: false
# user_id カラム + インデックス + 外部キー

削除

remove_foreign_key :posts, :users
remove_foreign_key :posts, column: :author_id

NOT NULL とデフォルト値

デフォルト値付き

add_column :users, :role, :integer, default: 0

NOT NULL

add_column :users, :email, :string, null: false

⚠️ 既存データがある場合、デフォルトなしで NOT NULL 追加すると失敗:

# ❌ 既存データ全部に NULL → エラー
add_column :users, :email, :string, null: false

# ✅ デフォルト値で全行を埋めてから NOT NULL
add_column :users, :email, :string, default: "", null: false

Zero-downtime での NOT NULL 追加(巨大テーブル向け)

3段階に分ける:

# Step 1: カラム追加(nullable)
class AddEmailToUsersStep1 < ActiveRecord::Migration[8.0]
  def change
    add_column :users, :email, :string
  end
end

# Step 2: アプリ側でデフォルト値設定 + データ移行ジョブ実行

# Step 3: NOT NULL 制約追加
class AddEmailToUsersStep3 < ActiveRecord::Migration[8.0]
  def change
    change_column_null :users, :email, false
  end
end

マイグレーション内でのデータ操作

execute(生SQL)

class UpdateUserStatuses < ActiveRecord::Migration[8.0]
  def up
    execute "UPDATE users SET status = 1 WHERE active = true"
  end
  
  def down
    execute "UPDATE users SET status = 0"
  end
end

ActiveRecord モデルを使う

class UpdateUserStatuses < ActiveRecord::Migration[8.0]
  def up
    # ⚠️ マイグレーション内では本物のモデルを使わない
    say_with_time "Updating user statuses..." do
      User.reset_column_information
      User.where(active: true).update_all(status: 1)
    end
  end
end

⚠️ マイグレーション内で本物のモデルクラスを使うのは推奨されない。理由:

  • マイグレーションは過去のスキーマで動く可能性
  • モデルクラスが将来削除・改名されると古いマイグレーションが壊れる

一時的なモデル定義

class UpdateUserStatuses < ActiveRecord::Migration[8.0]
  class MigrationUser < ActiveRecord::Base
    self.table_name = "users"
  end
  
  def up
    MigrationUser.where(active: true).update_all(status: 1)
  end
end

実行コマンド完全リファレンス

基本

# 保留マイグレーション全実行
bin/rails db:migrate

# 環境指定
bin/rails db:migrate RAILS_ENV=production
RAILS_ENV=test bin/rails db:migrate

状態確認

bin/rails db:migrate:status

出力例:

database: myapp_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20260101000001  Create users
   up     20260102000001  Create posts
  down    20260601000001  Add email to users  ← 保留

ロールバック

# 直前の1つを戻す
bin/rails db:rollback

# 3つ戻す
bin/rails db:rollback STEP=3

特定バージョンへ

# そのバージョンまで進める
bin/rails db:migrate VERSION=20260601000001

# そのバージョンまで戻す(含まない)
bin/rails db:rollback VERSION=20260601000001

個別 up/down

# 特定バージョンを up
bin/rails db:migrate:up VERSION=20260601000001

# 特定バージョンを down
bin/rails db:migrate:down VERSION=20260601000001

redo(やり直し)

# 直前の1つを down → up
bin/rails db:migrate:redo

# 2つ
bin/rails db:migrate:redo STEP=2

スキーマ操作

# schema.rb からロード(マイグレーション履歴なしに再構築)
bin/rails db:schema:load

# schema.rb を現在のDB状態から再生成
bin/rails db:schema:dump

リセット系

# DB完全リセット(drop + create + schema:load + seed)
bin/rails db:reset

# 同上(drop + create + migrate + seed)
bin/rails db:setup

# DB作成のみ
bin/rails db:create

# DB削除のみ
bin/rails db:drop

# 安全な選択肢(作成 or 既存ならスキップ)
bin/rails db:prepare

test 環境

# test DB を最新スキーマに
bin/rails db:test:prepare

# test DB を完全クリーン
bin/rails db:test:purge

seed

# db/seeds.rb 実行
bin/rails db:seed

マルチDB対応

Rails 6+ では複数DB管理が標準化。

database.yml

production:
  primary:
    <<: *default
    database: myapp_production
  cache:
    <<: *default
    database: myapp_cache
    migrations_paths: db/cache_migrate
  queue:
    <<: *default
    database: myapp_queue
    migrations_paths: db/queue_migrate

マルチDB専用コマンド

# 全DB分実行
bin/rails db:migrate

# 特定DBのみ
bin/rails db:migrate:primary
bin/rails db:migrate:cache
bin/rails db:migrate:queue

# 状態確認
bin/rails db:migrate:status
bin/rails db:migrate:status:cache

# ロールバック
bin/rails db:rollback:primary
bin/rails db:rollback:cache

特定DBへのマイグレーション作成

bin/rails g migration CreateCacheEntries --database cache
# db/cache_migrate/ 配下に生成される

詳細はSolid Queue 使い方Solid Cache 使い方Solid Cable 使い方 も参照。


Zero-downtime migration

本番サービスを止めずにスキーマ変更するためのテクニック。

1. 巨大テーブルのインデックス追加

class AddIndexToUsersEmail < ActiveRecord::Migration[8.0]
  disable_ddl_transaction!
  
  def change
    add_index :users, :email, algorithm: :concurrently
  end
end

2. NOT NULL の段階的追加

# Step 1: カラム追加(nullable, デフォルト値あり)
add_column :users, :email_verified, :boolean, default: false

# Step 2: 既存データ更新(マイグレーション or バックグラウンドジョブ)

# Step 3: NOT NULL 制約追加
change_column_null :users, :email_verified, false

3. カラム削除の段階的処理

# Step 1: モデルから削除(コードでアクセスしない)
# class User < ApplicationRecord
#   self.ignored_columns = ["old_column"]
# end

# Step 2: デプロイして既存リクエストでもアクセスされないことを確認

# Step 3: カラム削除マイグレーション
def change
  remove_column :users, :old_column, :string
end

4. カラム rename を避ける

# ❌ ダウンタイムリスクあり
rename_column :users, :name, :full_name

# ✅ 段階的に
# 1. 新カラム追加 (full_name)
# 2. データコピー
# 3. アプリで新旧両方アクセス可能に
# 4. 古いカラム削除

5. strong_migrations gem

# Gemfile
gem "strong_migrations"

危険なマイグレーションを検知し、修正方法を提示してくれます:

=== Dangerous operation detected ===

Adding a column with a non-null default requires that existing rows be updated.

Instead:
1. Add the column without a default value
2. Backfill the column
3. Change the default

関連 generator

model 生成

bin/rails g model User name:string email:string
# → app/models/user.rb
# → db/migrate/xxx_create_users.rb
# → test/models/user_test.rb
# → test/fixtures/users.yml

resource 生成

bin/rails g resource Post title:string body:text
# → モデル + マイグレーション + コントローラ + ルーティング

scaffold 生成

bin/rails g scaffold Post title:string body:text
# → モデル + マイグレーション + コントローラ + ビュー + ルーティング + テスト

ありがちなミス・対処

1. 既存マイグレーションを編集してしまう

# db/migrate/20260101000001_create_users.rb
# 直接編集 → 既に migrate 済みのため、変更が反映されない

対処: 新しいマイグレーションを作って変更:

bin/rails g migration ChangeUsersFooColumn

または、ローカルで一旦ロールバックしてから編集:

bin/rails db:rollback
# 編集
bin/rails db:migrate

⚠️ 既にチームでpush済みのマイグレーションの編集は NG。

2. ロールバック不可能なマイグレーション

def change
  remove_column :users, :email   # 型不明 → IrreversibleMigration
end

対処: 型を指定

def change
  remove_column :users, :email, :string
end

3. 巨大テーブルへの NOT NULL 追加でサービス停止

def change
  add_column :users, :email, :string, null: false
  # 既存100万行の users にエラー
end

対処: 段階的に追加(前述のZero-downtime参照)。

4. データ移行とスキーマ変更を混在

# ❌ スキーマ + データ更新 + 別スキーマ変更 → 失敗時の復旧難
def change
  add_column :users, :status, :integer
  User.update_all(status: 0)
  remove_column :users, :active
end

対処: マイグレーションを分割

# 1. add_column
# 2. データ移行ジョブ
# 3. remove_column

5. timestamps 忘れ

create_table :products do |t|
  t.string :name
  # t.timestamps が無い → created_at, updated_at がない
end

対処: 後から追加

add_timestamps :products, default: -> { 'CURRENT_TIMESTAMP' }
change_column_default :products, :created_at, from: nil, to: nil
change_column_default :products, :updated_at, from: nil, to: nil

または最初から含める:

create_table :products do |t|
  t.string :name
  t.timestamps   # ← 必須
end

6. references の foreign_key 忘れ

# ❌ ID カラムだけ、外部キー制約なし
t.references :user

# ✅ 外部キー制約も追加
t.references :user, null: false, foreign_key: true

7. インデックス未付与でクエリ遅延

# email でログイン検索するのに index なし
add_column :users, :email, :string
# → User.find_by(email: ...) が遅い

対処:

add_index :users, :email, unique: true

8. PendingMigrationError 発生

詳細はActiveRecord::PendingMigrationError の記事


よくある質問(FAQ)

Q1. change と up/down の使い分けは?

状況推奨
シンプルな add/remove/createchange
複雑なロジック・データ変換up/down
ロールバック不可能な処理up/down(down で raise)

Q2. schema.rb と structure.sql どちらを使う?

選択肢用途
schema.rb(デフォルト)DB非依存、シンプル
structure.sqlPostgreSQL拡張、複雑な制約使用時
# config/application.rb
config.active_record.schema_format = :sql   # structure.sql 使用

Q3. マイグレーションの実行順序は?

ファイル名先頭のタイムスタンプ(UTC)順。手動で書き換えてはダメ

複数人が同時に作成する場合、ファイル名のタイムスタンプ衝突に注意。

Q4. 古いマイグレーションを削除しても良い?

OK だが慎重に:

  • 削除後は db:schema:load でしか新規DBを構築できなくなる
  • 既存環境への影響なし(schema_migrations が記録)

新規開発者向けに README に bin/rails db:schema:load 推奨を明記。

Q5. 本番デプロイで失敗しないコツは?

  1. ステージングで事前テスト
  2. strong_migrations で危険検知
  3. Zero-downtime 設計
  4. バックアップ取得
  5. デプロイスクリプトに db:migrate 含める

Q6. テスト環境でのマイグレーション

# CI セットアップで
bin/rails db:test:prepare
# または
bin/rails db:schema:load RAILS_ENV=test

Q7. timestamps の精度

PostgreSQL では microsecond 精度ですが、Rails の t.timestamps はデフォルトで 6桁の精度:

t.timestamps  # precision: 6 がデフォルト(Rails 7+)

明示変更も可能:

t.timestamps precision: 3   # ミリ秒

Q8. UUIDを主キーにしたい

PostgreSQL 拡張を有効化:

enable_extension "pgcrypto"

create_table :products, id: :uuid do |t|
  t.string :name
end

または Rails 7.1+ なら:

create_table :products, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
  t.string :name
end

Q9. JSON 列の使い方

# PostgreSQL: jsonb 推奨(インデックス可能)
add_column :products, :metadata, :jsonb, default: {}

# MySQL: json
add_column :products, :metadata, :json

# 利用
product.metadata = { tags: ["new", "sale"], expires_at: "2026-12-31" }
product.metadata["tags"]

Q10. enum 列の使い方

# integer カラムで実装
add_column :users, :status, :integer, default: 0, null: false

# モデル側
class User < ApplicationRecord
  enum :status, { pending: 0, active: 1, banned: 2 }
end

User.active   # WHERE status = 1
user.pending?
user.active!

Q11. マイグレーションのテスト

# spec/migrations/xxx_spec.rb
require 'rails_helper'

RSpec.describe "AddEmailToUsers", type: :migration do
  # 検証
end

gem 'rails-controller-testing' 等で支援。実務ではあまりやらない。

Q12. 失敗したマイグレーションの復旧

# 状態確認
bin/rails db:migrate:status

# down のままならファイル修正後 migrate
# up になっていて変更が不完全なら、ロールバックして修正後 migrate
bin/rails db:rollback
# ファイル修正
bin/rails db:migrate

DB が壊れたらバックアップから復旧。


参考リンク・関連資料

Rails 公式

関連 Gem

関連記事(本サイト)


まとめ

rails db:migrate は Rails 開発の基礎ですが、奥が深いツール。要点を再整理します。

  • 基本構造: db/migrate/YYYYMMDDHHMMSS_migration_name.rb ファイル + ActiveRecord::Migration[8.0] 継承クラス
  • 作成: rails g migration でテンプレ生成、命名規約で自動生成も可能
  • 記述: change メソッド(シンプル)または up/down(複雑)
  • カラム型: string/text/integer/decimal/datetime/json/jsonb/uuid 等
  • テーブル操作: create_tableadd_columnadd_indexadd_foreign_key
  • 実行: db:migrate、状態確認は db:migrate:status
  • ロールバック: db:rollback、特定バージョンは VERSION=...
  • マルチDB: db:migrate:cachedb:migrate:queue 等の専用コマンド
  • Zero-downtime: コンカレントインデックス、段階的 NOT NULL、ignored_columns
  • 安全策: strong_migrations、ステージング検証、バックアップ
  • 避けるべき: 既存マイグレーションの編集、巨大データへの NOT NULL、複雑な混在処理

これらの知識は、Rails アプリの設計・開発・運用・本番デプロイすべてで活用できます。本記事をブックマークしておけば、db:migrate 関連のあらゆる作業を効率化できます。


本記事は2026年6月時点の情報をもとに、Ruby on Rails 7.x / 8.x での動作確認・公式ドキュメントに基づき作成しています。Rails のバージョンによって挙動が異なる場合があるため、最新の情報はRails公式ガイドもあわせてご確認ください。