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?

migration

0
Last updated at Posted at 2026-08-12

migrationとは?

Railsを触っていると、こんなコードを目にすることがあります。

class CreateCompanies < ActiveRecord::Migration[8.0]
  def change
    create_table :companies do |t|
      t.string :name
      t.string :address

      t.timestamps
    end
  end
end

最初に見たとき、

migrationって何?
なぜこのコードからテーブルが作られるの?
do |t|tって何?

と疑問に思いました。

今回は、migrationの基本から、自分が特につまずいたdo |t|まで整理します。


1. migrationとは何か?

一言でまとめると

migration(マイグレーション)とは、

データベースの構造変更と、その変更履歴を管理するための仕組み

です。

例えば、最初に次のusersテーブルを作ったとします。

id name
1 田中
2 佐藤

開発を進めていると、

「ユーザーのメールアドレスも保存したい!」

となるかもしれません。

その場合、DBを次のように変更する必要があります。

id name email
1 田中 tanaka@example.com
2 佐藤 sato@example.com

つまり、

変更前

users
├── id
└── name

       ↓

「emailも保存したい!」

       ↓

変更後

users
├── id
├── name
└── email  ← 追加

このようなDBの構造変更を管理するのがmigrationです。


なぜmigrationが必要なのか?

「DBを直接変更すればいいのでは?」

と思うかもしれません。

しかし、チーム開発を考えてみます。

例えばAさんが、

usersテーブルにemailを追加

したとします。

DBだけを直接変更すると、

AさんのDB

users
├── id
├── name
└── email

なのに、

BさんのDB

users
├── id
└── name

というように、開発者ごとにDB構造がズレる可能性があります。

そこで、

migrationファイル

「usersにemailを追加してください」

というDB変更の記録をコードとして残します。

イメージすると、

             migration
                 │
       ┌─────────┴─────────┐
       ↓                   ↓
    AさんのDB            BさんのDB
       │                   │
       ↓                   ↓
id / name / email     id / name / email

のように、同じmigrationを実行することでDB構造を揃えられます。


2. 基本的な使い方

実際に、

会社情報を保存するcompaniesテーブルを作る

という例で考えてみます。

保存したい情報は、

情報 内容
会社名 name
住所 address
従業員数 employees

とします。


① migrationファイルを作る

Railsでは、例えば次のようなコマンドでmigrationを作成できます。

rails generate migration CreateCompanies

すると、

db/
└── migrate/
    └── 20260813000000_create_companies.rb

のようなmigrationファイルが作られます。


② テーブルの構造を書く

migrationに次のように書きます。

class CreateCompanies < ActiveRecord::Migration[8.0]
  def change
    create_table :companies do |t|
      t.string :name
      t.string :address
      t.integer :employees

      t.timestamps
    end
  end
end

それぞれのコードを対応させると、

migration 意味
create_table :companies companiesテーブルを作る
t.string :name 文字列型のnameを作る
t.string :address 文字列型のaddressを作る
t.integer :employees 整数型のemployeesを作る
t.timestamps created_atとupdated_atを作る

となります。


③ migrationを実行する

migrationファイルを作っただけでは、まだDBは変更されません。

rails db:migrate

を実行します。

流れとしては、

migrationファイルを作る
        │
        ↓
DBをどう変更するかを書く
        │
        ↓
rails db:migrate
        │
        ↓
migrationが実行される
        │
        ↓
実際のDBが変更される

というイメージです。


④ どんなテーブルができる?

先ほどのmigrationを実行すると、

companies
┌────┬──────────┬─────────┬───────────┬────────────┬────────────┐
│ id │ name     │ address │ employees │ created_at │ updated_at │
├────┼──────────┼─────────┼───────────┼────────────┼────────────┤
│ 1  │ ABC会社  │ 東京都  │ 100       │ ...        │ ...        │
│ 2  │ XYZ会社  │ 神奈川  │ 50        │ ...        │ ...        │
└────┴──────────┴─────────┴───────────┴────────────┴────────────┘

という構造になります。

コードとの対応関係を見ると、

create_table :companies
        │
        └──────────────→ companiesテーブル

Railsがデフォルトで作成
        │
        └──────────────→ id

t.string :name
        │
        └──────────────→ name

t.string :address
        │
        └──────────────→ address

t.integer :employees
        │
        └──────────────→ employees

t.timestamps
        │
        ├──────────────→ created_at
        │
        └──────────────→ updated_at

となっています。


3. よくあるエラー・失敗は?

migrationで遭遇する可能性があるものとして、

Table 'companies' already exists

というエラーがあります。

意味としては、

companiesテーブルはすでに存在しています

というものです。


migrationのUP / DOWN

migrationの状態は、

rails db:migrate:status

で確認できます。

例えば、

Status   Migration ID    Migration Name
------------------------------------------------
up       20260801090000  Create users
up       20260802100000  Add email to users
down     20260803120000  Create companies

のように表示されます。

UP

UP
↓
そのmigrationは実行済み

DOWN

DOWN
↓
そのmigrationはまだ実行されていない

「テーブルはあるのにDOWN」という状態

ここで少しややこしい状態があります。

例えば、

migrationの管理状態

CreateCompanies
      ↓
     DOWN

「まだ実行されていない」

なのに、実際のDBを見ると、

DB

companies
├── id
├── name
└── address

↑
すでに存在する

という状態です。

この状態で、

rails db:migrate

を実行すると、RailsはmigrationがDOWNなので、

Rails

「CreateCompaniesはDOWNだ」
        ↓
「まだ実行してないんだな」
        ↓
「companiesを作ろう」

とします。

しかしDB側は、

DB

「companiesはもう存在してるよ」

となります。

その結果、

Rails
「companies作ります!」

        ↓

DB
「もうあります!」

        ↓

Table 'companies' already exists

というエラーにつながります。

そのため、

「テーブルがすでにあるなら、そのままでいいのでは?」

とは限りません。

migrationの実行履歴と実際のDB構造が一致していることが重要です。

特に会社のリポジトリや共有DBでは、自分の判断でmigrationファイルを削除したりDBを変更したりせず、状況を確認してから対応する必要があります。


4. 今回AIに質問してつまずいたところ

今回、自分が特につまずいたのが、

create_table :companies do |t|

の、

do |t|

でした。

最初は、

tって何?
なぜ急にtが出てきた?

という状態でした。


do |t|はRails独自の文法ではない

まず重要だったのが、

do |t|

はRails独自の文法ではなく、Rubyのブロックの仕組みだということです。

ざっくり、

渡されてきたものをtという変数で受け取る

と考えると理解しやすくなりました。


tには何が入っている?

例えば、

create_table :companies do |t|
  t.string :name
  t.string :address
end

では、Rails側からテーブルを定義するためのオブジェクトが渡されます。

それをtで受け取っています。

create_table :companies

        ↓

Rails
「companiesテーブルを
 定義するためのものを用意したよ」

        ↓
       渡す

        ↓

       |t|

        ↓

tを使ってテーブルを定義

tという名前である必要はない

ここも理解の助けになりました。

例えば、

create_table :companies do |table|
  table.string :name
  table.string :address
end

としても考え方は同じです。

tは特別なキーワードではありません。

最初は、

table.string :name

と読み替えると、

「テーブルにstring型のnameを追加する」

と理解しやすくなりました。


t.string :nameをさらに分解する

t.string :name

は、

t
↓
テーブルを定義するためのオブジェクト


.string
↓
string型のカラムを定義するメソッド


:name
↓
nameというカラム名

という関係になっています。

つまり、

「tさん、string型のnameカラムを定義してください」

くらいのイメージです。


Rubyのeachと比較すると分かりやすかった

例えばRubyでは、

names = ["田中", "佐藤", "鈴木"]

names.each do |name|
  puts name
end

と書けます。

ここでは、

["田中", "佐藤", "鈴木"]

1回目
"田中"
  ↓
|name|
  ↓
name = "田中"


2回目
"佐藤"
  ↓
|name|
  ↓
name = "佐藤"


3回目
"鈴木"
  ↓
|name|
  ↓
name = "鈴木"

というように値を受け取っています。

create_tableも、渡されるものは違いますが、

each

値を渡す
   ↓
|name|
   ↓
nameとして使う

に対して、

create_table

テーブル定義用オブジェクトを渡す
           ↓
          |t|
           ↓
       tとして使う

という基本的な考え方は同じでした。


最後に整理

今回の内容を一枚にまとめると、

            migration
                │
                │
     DB構造の変更を管理する
                │
                ↓
    create_table :companies
                │
                │
     companiesテーブルを作る
                │
                ↓
             do |t|
                │
                │
 Railsからテーブル定義用の
 オブジェクトを受け取る
                │
                ↓
                t
        ┌───────┼─────────┐
        ↓       ↓         ↓
     .string  .integer  .timestamps
        ↓       ↓         ↓
      name   employees  created_at
                       updated_at

最初はmigrationを、

「なんとなくDBのテーブルを作るコード」

と理解していました。

しかし今回調べてみて、

migrationはDB構造の変更履歴を管理する仕組みで、create_tableのブロックではRailsから渡されたテーブル定義用オブジェクトをtで受け取り、そのオブジェクトのメソッドを使ってカラムを定義している

というところまで理解できました。

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?