0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Railsのマイグレーションとは?受講生管理システムで仕組みを理解する

0
Posted at

Railsを使って開発していると、次のようなコマンドをよく目にします。

bin/rails db:migrate

初心者の私は、

「マイグレーションって何をしているんだろう?」

「DBの変更管理って聞くけど、実際にDBを変更しているの?」

と疑問に思いました。

この記事では、受講生管理システムを例にして、Railsのマイグレーションの仕組みを説明します。


1. そもそもマイグレーションとは?

一言でいうと、Railsのマイグレーションとは、

データベースの構造変更をコードとして管理し、実際のDBに適用する仕組み

です。

例えば、受講生管理システムを作っているとします。

最初は、受講生を管理するために次のようなテーブルを作りました。

students

id
name
age

しかし、後から、

「受講生のメールアドレスも管理したい」

という要件が追加されたとします。

そこで、studentsテーブルに、

email

というカラムを追加することになりました。


2. DBを直接変更することもできる

PostgreSQLを直接操作するなら、例えば次のようなSQLを実行できます。

ALTER TABLE students
ADD COLUMN email varchar(255);

これでDBには、

students

id
name
age
email  ← 追加

という状態ができます。

しかし、これだけでは問題があります。

例えば開発メンバーが3人いた場合、

開発者A → DB変更済み
開発者B → DB変更していない
開発者C → DB変更していない

という状態になる可能性があります。

また、

「いつ、誰が、なぜemailカラムを追加したの?」

という変更履歴も分かりにくくなります。

そこでRailsのマイグレーションを使います。


3. Migrationファイルを作る

Railsでは、DB変更をMigrationファイルとして管理します。

例えば、

db/migrate/
└── 20260818000000_add_email_to_students.rb

というMigrationを作ります。

中身は例えば、

class AddEmailToStudents < ActiveRecord::Migration[7.0]
  def change
    add_column :students, :email, :string
  end
end

となります。

ここで、

add_column :students, :email, :string

は、

studentsテーブルにemailという文字列型のカラムを追加する

という意味です。


4. Migrationは「変更履歴」だけではない

ここが重要です。

Migrationは単なるメモではありません。

実際にDBを変更するためのRubyプログラムです。

例えば、

add_column :students, :email, :string

というMigrationを作っただけでは、DBはまだ変わりません。

Migrationを実行する必要があります。

bin/rails db:migrate

すると、

Migrationファイル
        ↓
Rubyコードを実行
        ↓
Active RecordがSQLを生成
        ↓
PostgreSQLへSQLを送信
        ↓
studentsテーブルが変更される

という流れになります。


5. db:migrateを実行すると何が起きる?

例えば、現在のDBが、

students

id
name
age

だったとします。

ここで、

bin/rails db:migrate

を実行します。

すると、Migrationに書かれた、

add_column :students, :email, :string

が実行されます。

Railsが内部でSQLを生成し、

ALTER TABLE students
ADD COLUMN email varchar(255);

のようなSQLをDBに送ります。

結果、

students

id
name
age
email  ← 追加された

となります。


6. 「どのMigrationを実行したか」はどう管理している?

ここで登場するのが、

schema_migrations

というテーブルです。

Railsは、Migrationを実行すると、

「このMigrationはもう実行しました」

という情報をschema_migrationsに記録します。

例えば、

schema_migrations

version
----------------
20260801000000
20260810000000
20260818000000

となります。

この数字はMigrationファイル名の先頭にある数字です。

例えば、

20260818000000_add_email_to_students.rb

なら、

20260818000000

がVersionになります。


7. Migrationファイルとschema_migrationsを比較する

例えば、プロジェクトのdb/migrateに次の3つのMigrationがあるとします。

db/migrate/

20260801000000_create_students.rb
20260810000000_add_age_to_students.rb
20260818000000_add_email_to_students.rb

一方、DBのschema_migrationsが、

20260801000000
20260810000000

だったとします。

するとRailsは、

Migrationファイル
--------------------------
20260801000000
20260810000000
20260818000000

と、

schema_migrations
--------------------------
20260801000000
20260810000000

を比較します。

すると、

20260818000000

だけがDB側にありません。

つまり、

add_email_to_studentsのMigrationがまだ適用されていない」

と判断できます。


8. イメージとしては「チェックリスト」

初心者の場合は、Migrationの管理をチェックリストとして考えると分かりやすいです。

【Migrationファイル】

☑ 20260801000000
☑ 20260810000000
☐ 20260818000000

DB側のschema_migrationsは、

【DBに適用済み】

☑ 20260801000000
☑ 20260810000000

という状態です。

そのためRailsは、

☐ 20260818000000

「未適用Migration」

と判断します。


9. 未適用Migrationがあるとどうなる?

例えば、新しく

20260818000000_add_email_to_students.rb

というMigrationを作ったとします。

しかし、DBにはまだ適用していません。

この状態でRailsのdevelopment環境を動かすと、

ActiveRecord::PendingMigrationError

が発生することがあります。

例えば、

Migrations are pending.

To resolve this issue, run:

bin/rails db:migrate

というエラーが表示されます。

これは、

「アプリケーションのコードには新しいDB変更が含まれていますが、DBにはまだ反映されていません」

という意味です。


10. なぜ関係ない画面までエラーになるの?

ここは少し分かりにくいポイントです。

例えば今回追加したのが、

students.email

だったとします。

しかし、受講生一覧画面では、

students.name

しか使っていないとします。

すると、

「emailを使っていないなら、受講生一覧画面は動くのでは?」

と思います。

しかしRailsのdevelopment環境では、リクエスト処理の前段階でMigrationの未適用状態をチェックする仕組みがあります。

そのため、

受講生一覧画面
      ↓
Rails
      ↓
Migrationチェック
      ↓
未適用Migrationあり
      ↓
PendingMigrationError

となることがあります。

つまり、

emailとは関係ない処理

であっても、Migrationが未適用ならリクエスト自体がブロックされる場合があります。

これは、

DBとアプリケーションの構造が一致していない状態でアプリケーションを動かさない

ための安全機構です。


11. db:migrateを実行するとエラーが消える理由

そこで、

bin/rails db:migrate

を実行します。

すると、

① 未適用Migrationを探す
        ↓
② add_email_to_studentsを実行
        ↓
③ studentsテーブルにemail追加
        ↓
④ schema_migrationsにVersionを記録

となります。

DBは、

students

id
name
age
email

になります。

そして、

schema_migrations

20260801000000
20260810000000
20260818000000

となります。

これでRailsは、

Migrationファイル
        ↓
20260818000000あり

schema_migrations
        ↓
20260818000000あり

と確認できるため、

「すべてのMigrationが適用済み」

と判断します。


12. db/schema.rbとは?

Migrationを調べていると、

db/schema.rb

というファイルも登場します。

これは、

現在のDBがどのような構造になっているかを表したファイル

です。

例えば、

create_table "students" do |t|
  t.string "name"
  t.integer "age"
  t.string "email"
end

のように記録されています。


13. Migrationとschema.rbの違い

ここは混同しやすいので整理します。

Migration

「DBをどう変更したか」

です。

例えば、

add_column :students, :email, :string

です。

schema.rb

「現在のDBがどうなっているか」

です。

例えば、

create_table "students" do |t|
  t.string "name"
  t.integer "age"
  t.string "email"
end

です。

つまり、

Migration
   ↓
DBを変更する
   ↓
現在のDB構造
   ↓
schema.rb

という関係です。


14. 受講生管理システムで考えると

例えば、受講生管理システムを開発していて、最初は、

students

id
name
age

だったとします。

その後、要件変更で、

メールアドレスを管理したい

となりました。

そこでMigrationを作ります。

class AddEmailToStudents < ActiveRecord::Migration[7.0]
  def change
    add_column :students, :email, :string
  end
end

そして、

bin/rails db:migrate

を実行します。

すると、

【変更前】

students
----------------
id
name
age


        ↓ Migration


【変更後】

students
----------------
id
name
age
email

となります。

さらにschema_migrationsには、

20260818000000

が記録されます。

このようにして、

「受講生管理システムのDBに、メールアドレスを追加した」

というDB変更を、コードと履歴として管理できます。


15. チーム開発でMigrationが便利な理由

例えば受講生管理システムを3人で開発しているとします。

Aさん
Bさん
Cさん

Aさんが、

「受講生にメールアドレスを追加する」

という機能を実装しました。

AさんはMigrationを作ります。

20260818000000_add_email_to_students.rb

そしてGitにコミットします。

Git
└── 20260818000000_add_email_to_students.rb

BさんとCさんが最新コードを取得すると、

git pull

によってMigrationファイルも取得できます。

そして、

bin/rails db:migrate

を実行すれば、BさんとCさんのDBにも同じ変更を適用できます。

Aさん
  ↓
Migration作成
  ↓
Git
  ↓
Bさん・Cさん
  ↓
db:migrate
  ↓
それぞれのDBに同じ変更

これがMigrationの大きなメリットです。


16. MigrationはGitと相性がいい

MigrationはGitで管理できます。

例えば、

Git
│
├── アプリケーションコード
│
└── db/migrate
      ├── 20260801000000_create_students.rb
      ├── 20260810000000_add_age_to_students.rb
      └── 20260818000000_add_email_to_students.rb

という構成になります。

そのため、

「このDB変更は誰が作ったのか」

「どのタイミングで追加されたのか」

「どんな変更をしたのか」

をコードレビューで確認できます。


17. MigrationはRailsだけの機能?

「DBマイグレーション」という考え方自体はRailsだけのものではありません。

JavaのSpring Bootでも、DB変更を管理するために、

  • Flyway
  • Liquibase

などのツールがよく使われます。

Railsの場合は、

Rails
├── Active Record
│   └── ORM
│
└── Active Record Migration
    └── DBスキーマ変更管理

という構成です。

Spring Bootでは、

Spring Boot
├── JPA / Hibernate
│   └── ORM
│
└── Flyway / Liquibase
    └── DBスキーマ変更管理

という構成が一般的です。

つまり、

DBの変更をコードとして管理する

という考え方は、Rails特有のものではありません。


18. db:migratedb:prepareの違い

Railsには、

bin/rails db:migrate

以外に、

bin/rails db:prepare

というコマンドもあります。

db:migrateは、

未適用のMigrationをDBに適用する

ためのコマンドです。

一方、db:prepareは、

DBをRailsアプリケーションから利用できる状態に準備する

ためのコマンドです。

そのため、新しく開発環境を構築するときなどに利用されます。

例えば、

新しくプロジェクトを取得
        ↓
DBがまだ存在しない
        ↓
db:prepare
        ↓
DBを準備
        ↓
必要なMigrationなどを適用
        ↓
アプリケーションを利用可能にする

というイメージです。


19. Migrationの全体像

ここまでの内容を、受講生管理システムでまとめると次のようになります。

┌──────────────────────────────┐
│          db/migrate/         │
│                              │
│  create_students.rb          │
│  add_age_to_students.rb      │
│  add_email_to_students.rb    │
└──────────────┬───────────────┘
               │
               │ db:migrate
               ▼
┌──────────────────────────────┐
│         PostgreSQL           │
│                              │
│  students                    │
│  ├── id                      │
│  ├── name                    │
│  ├── age                     │
│  └── email                   │
└──────────────┬───────────────┘
               │
               │ 適用済みVersionを記録
               ▼
┌──────────────────────────────┐
│      schema_migrations       │
│                              │
│  20260801000000              │
│  20260810000000              │
│  20260818000000              │
└──────────────┬───────────────┘
               │
               │ 現在のDB構造を反映
               ▼
┌──────────────────────────────┐
│         db/schema.rb         │
│                              │
│  students                    │
│  ├── id                      │
│  ├── name                    │
│  ├── age                     │
│  └── email                   │
└──────────────────────────────┘

20. まとめ

Railsのマイグレーションについて、最低限覚えておきたいのは次の5つです。

① Migrationとは

DBスキーマの変更をコードとして管理し、実際のDBへ適用する仕組み

です。

② Migrationファイル

db/migrate/

に保存されます。

例えば、

20260818000000_add_email_to_students.rb

のようなファイルです。

db:migrate

bin/rails db:migrate

を実行すると、未適用のMigrationが実行され、DBが変更されます。

schema_migrations

「どのMigrationを適用済みか」

をDB側で管理します。

schema.rb

「現在のDBがどのような構造になっているか」

を表します。


最後に

マイグレーションは、単に

「DBの変更履歴を残すもの」

と考えるより、

「DBの変更をコード化して、チームで同じDB変更を再現できるようにする仕組み」

と考えると分かりやすいです。

受講生管理システムであれば、

受講生テーブルを作る
        ↓
年齢カラムを追加する
        ↓
メールアドレスを追加する
        ↓
電話番号を追加する
        ↓
住所を追加する

といったDBの変更を、Migrationとして順番に管理できます。

Migration 1
受講生テーブルを作成
        ↓
Migration 2
年齢を追加
        ↓
Migration 3
メールアドレスを追加
        ↓
Migration 4
電話番号を追加
        ↓
現在のDB

このように、アプリケーションの成長に合わせてDBの構造を安全に変更・管理していくための仕組みがRailsのマイグレーションです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?