マイグレーションとは
layout: page
説明
直接SQLを使わずに、データベースのテーブルやカラムなどの構造を変更できる仕組み
特徴
- db/migrateディレクトリ以下にあるRubyで書かれたファイル
- ファイル名はタイムスタンプ(西暦、月、日、時、分、秒)とアンダースコア(_)で始まり、クラス名のすべての大文字を小文字にしたもの
- 別々のマイグレーションファイルに同じ名前のマイグレーションクラスを記述できない
- idという主キーを自動的に追加
- 実行するにはRakeタスク
- schema_infoテーブルに現在のバージョンが格納
簡単な例
class AddSsl < ActiveRecord::Migration
  def up
    add_column :accounts, :ssl_enabled, :boolean, default: true
  end
  def down
    remove_column :accounts, :ssl_enabled
  end
end
class TenderloveMigration < ActiveRecord::Migration
  def change
    create_table(:horses) do |t|
      t.column :content, :text
      t.column :remind_at, :datetime
    end
  end
end
利用可能なメソッド
- create_table
- drop_table
- change_table
- rename_table
- add_column
- rename_column
- change_column
- remove_column
- add_index
- remove_index
- remove_index
サポートしているデータベース
- MySQL
- PostgreSQL
- SQLite
- SQL Server
- Sybase
- Oracle
カラムをバージョンアップ
layout: page
説明
データベースのカラムをバージョンアップ
upメソッドはロールバックできない処理をする際に主に使用
使い方
def up
end
例
pagesテーブルにnameカラムをstring型で作成
def up
  create_table :pages do |t|
    t.string :name
    t.string :category
  end
end
ソースコード
カラムをバージョンダウン
layout: page
説明
データベースのカラムをバージョンダウン
ロールバックできない処理の際に主に使用
使い方
def down
end
例
基本的な使い方
def down
  drop_table :pages
end
ソースコード
カラムを変更
layout: page
説明
データベースのカラムを変更
使い方
change(カラム名, 型 [, オプション])
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :limit | カラムの桁数を指定 | |
| :default | デフォルト値を指定 | |
| :null | NULL値を許可するか | true | 
| :precision | :decimal、:numeric、:datetime、および:time型の精度を指定 | |
| :scale | :decimal、:numeric型の小数点以下の桁数 | |
| :collation | :stringまたは:textの照合順序を指定 | |
| :comment | カラムのコメントを指定。データベース管理ツールなどで閲覧が可能 | 
例
データベースのカラムを変更
t.change(:description, :text)
カラムの桁数を指定して変更
t.change(:name, :string, limit: 80)
ソースコード
テーブルを作成
layout: page
説明
テーブルを作成
使い方
create_table(テーブル名 [, オプション])
ブロック
create_table テーブル名  [, オプション] do |t|
  t.型 カラム名 [, カラムオプション]
end
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :id | 主キーを自動生成 | true | 
| :primary_key | 主キーのカラムの名前 | id | 
| :options | テーブルオプション | |
| :temporary | 一時テーブルとして作成 | false | 
| :force | テーブルを作成前に、既存のテーブルを削除 | false | 
| :if_not_exists | テーブルが存在するときにエラーにしない | false | 
| :as | テーブル作成時に使うSQL | 
カラムオプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :limit | カラムの桁数 | |
| :default | デフォルトの値 | |
| :null | nullを許可するか | true | 
| :precision | 数値の桁数 | |
| :scale | 小数点以下の桁数 | 
カラムの型
| データ方 | 説明 | 
|---|---|
| string | 文字列 | 
| text | 長い文字列 | 
| integer | 整数 | 
| float | 浮動小数 | 
| decimal | 精度の高い小数 | 
| datetime | 日時 | 
| timestamp | より細かい日時 | 
| time | 時間 | 
| date | 日付 | 
| binary | バイナリデータ | 
| boolean | Boolean型 | 
例
テーブルの作成
crate_table :products do |t|
  t.string :name
end
空のカラムを禁止
create_tabe :products |t|
  t.string :name, null: false
end
文字コードを指定してテーブルを作成
create_table :suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8'
主キーを指定してテーブルを作成
create_table(:objects, primary_key: 'guid') do |t|
  t.column :name, :string, limit: 80
end
プライマリーキーの無いテーブルを作成
create_table(:categories_suppliers, id: false) do |t|
  t.column :category_id, :integer
  t.column :supplier_id, :integer
end
ソースコード
テーブル名を変更
layout: page
説明
指定したテーブルの名前を変更
使い方
rename_table(現在のテーブル名, 新しいテーブル名)
例
now_tableからnew_tableに変更
rename_table :now_table, :new_table
ソースコード
テーブルを削除
layout: page
説明
指定したテーブルを削除
使い方
drop_table(:テーブル名 [, オプション])
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :force | 依存も削除 | false | 
| :if_exists | 存在する場合のみ削除 | false | 
例
productsテーブルを削除
drop_table :products
依存も削除
drop_table :care_reasons, force: :cascade
存在する場合のみ削除
drop_table :article_attributes, if_exists: true
ソースコード
テーブル定義を変更
layout: page
説明
テーブル定義を変更
使い方
change_table(テーブル名 [, オプション]) do |t|
  t.メソッド名(データ型) カラム名
end
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :bulk | 変更内容を1つのALTER TABLEにまとめるか | false | 
使用できるメソッド
| メソッド名 | 説明 | 
|---|---|
| index | インデックス | 
| change | カラムを変更 | 
| change_default | カラムのデフォルト値を変更 | 
| column | カラムの追加 | 
| rename | カラムの名前を変更 | 
| timestamps | タイムスタンプを追加 | 
| belongs_to | 関係を追加 | 
| remove | カラムを削除 | 
| remove_references | リファレンスの削除 | 
| remove_index | インデックスの削除 | 
| remove_timestamps | タイムスタンプの削除 | 
| references | 外部キーを追加 | 
データ型
| 型 | 説明 | 
|---|---|
| string | 文字列 | 
| text | 長い文字列 | 
| integer | 整数 | 
| float | 浮動小数 | 
| decimal | 精度の高い小数 | 
| datetime | 日時 | 
| timestamp | より細かい日時 | 
| time | 時間 | 
| date | 日付 | 
| binary | バイナリデータ | 
| boolean | Boolean型 | 
例
pagesテーブルにtext型のmemoを追加、titleにインデックスを設定
change_table :pages do |t|
  t.text :memo
  t.index :title
end
カラムの追加
change_table(:suppliers) do |t|
  t.column :name, :string, limit: 60
end
2つのカラムの追加
change_table(:suppliers) do |t|
  t.integer :width, :height, null: false, default: 0
end
タイムスタンプを追加
change_table(:suppliers) do |t|
  t.timestamps
end
外部キーを追加
change_table(:suppliers) do |t|
  t.references :company
end
複数カラムの削除
change_table(:suppliers) do |t|
  t.remove :company_id
  t.remove :width, :height
end
インデックスを削除
change_table(:suppliers) do |t|
  t.remove_index :company_id
end
ソースコード
テーブルを結合して作成
layout: page
説明
2つのテーブルを結合して新しいテーブルを作成
使い方
create_join_table(テーブル名1, テーブル名2 [, オプション])
オプション
| オプション | 説明 | 
|---|---|
| :table_name | テーブルの名前 | 
| :column_options | カラムのオプション | 
| :options | オプション | 
| :temporary | 一時テーブルとして作成 | 
| :force | テーブルを作成前に、既存のテーブルを削除 | 
例
2つのテーブルを結合して新しいテーブルを作成
create_join_table(:assemblies, :parts, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
# CREATE TABLE assemblies_parts (
#   assembly_id int NOT NULL,
#   part_id int NOT NULL,
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8
ソースコード
テーブルが存在するかチェック
layout: page
説明
テーブルが存在するかチェック
使い方
table_exists?(テーブル名)
例
テーブルが存在するかチェック
table_exists?(:developers)
ソースコード
結合テーブルを削除
layout: page
説明
結合テーブルを削除
使い方
drop_join_table(テーブル1, テーブル2 [, オプション])
オプション
| オプション | 説明 | 
|---|---|
| :table_name | テーブルの名前 | 
| :column_options | カラムのオプション | 
| :options | オプション | 
| :temporary | 一時テーブルとして作成 | 
| :force | テーブルを作成前に、既存のテーブルを削除 | 
例
結合テーブルを削除
drop_join_table(:assemblies, :parts)
オプション指定
drop_join_table(:assemblies, :parts, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
ソースコード
カラムを追加
layout: page
説明
指定したテーブルにカラムを追加
使い方
add_column(テーブル名 カラム名, タイプ [, オプション])
タイプ
| タイプ | 説明 | 
|---|---|
| :primary_key | プライマリーキー | 
| :string | 文字列型 | 
| :text | テキスト型 | 
| :integer | 整数型(4バイト) | 
| :bigint | 整数型(8バイト) | 
| :float | 浮動小数点数 | 
| :decimal | 固定長整数型 | 
| :numeric | 数値型 | 
| :datetime | 日付と時刻(1000-01-01 00:00:00.000000から9999-12-31 23:59:59.999999) | 
| :time | 時刻 (-838:59:59から838:59:59) | 
| :date | 日付(1000-01-01から9999-12-31) | 
| :binary | バイナリ文字列型 | 
| :boolean | 真偽値型 | 
上記以外のデータベース特有のタイプも指定できるが、非推奨
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :limit | カラムの桁数を指定 | |
| :default | デフォルト値を指定 | |
| :null | NULL値を許可するか | true | 
| :precision | :decimal、:numeric、:datetime、および:time型の精度を指定 | |
| :scale | :decimal、:numeric型の小数点以下の桁数 | |
| :collation | :stringまたは:textの照合順序を指定 | |
| :comment | カラムのコメントを指定。データベース管理ツールなどで閲覧が可能 | 
precisionとscaleについては、データベースによって差があるので注意が必要
例
カラムの追加
add_column :users, :group_id, :integer
カラムの桁数を指定
add_column :users, :picture, :binary, limit: 2.megabytes
# ALTER TABLE "users" ADD "picture" blob(2097152)
NULLを許可しない
add_column :articles, :status, :string, limit: 20, default: 'draft', null: false
# ALTER TABLE "articles" ADD "status" varchar(20) DEFAULT 'draft' NOT NULL
固定長整数型を指定
add_column :answers, :bill_gates_money, :decimal, precision: 15, scale: 2
# ALTER TABLE "answers" ADD "bill_gates_money" decimal(15,2)
配列を指定
add_column :users, :skills, :text, array: true
# ALTER TABLE "users" ADD "skills" text[]
データベース固有のかたを指定
add_column :shapes, :triangle, 'polygon'
# ALTER TABLE "shapes" ADD "triangle" polygon
ソースコード
カラム名を変更
layout: page
説明
指定したテーブルのカラム名を変更
名前を変更しても、そのカラムに関連付けられている既存のデータは破棄されない
使い方
rename_column(テーブル名, 変更するカラム名, 新しいカラム名)
例
指定したテーブルのカラム名を変更
rename_column :suppliers, :description, :name
ソースコード
カラムの定義を変更
layout: page
説明
既存のカラムの定義を変更
使い方
change_column(テーブル名,  カラム名, データ型 [, オプション])
オプション
| オプション | 説明 | 
|---|---|
| :limit | カラムの桁数を指定 | 
| :default | デフォルト値を指定 | 
| :null | NULL値を許可するか | 
| :precision | :decimal 型の精度を指定 | 
| :scale | :decimal 型の小数点以下の桁数 | 
| :collation | :stringまたは:textの照合順序を指定 | 
| :comment | カラムのコメントを指定。データベース管理ツールなどで閲覧が可能 | 
precisionとscaleについては、データベースによって差があるので注意が必要
例
usersテーブルのnameカラムをtext型に変更
change_column(:users, :name, :text)
文字数の最大を80に変更
change_column(:users, :name, :string, limit: 80)
null側を許可しないように変更
change_column(:users, :name, :string, null: dalse)
ソースコード
カラムを削除
layout: page
説明
指定したテーブルのカラムを削除
使い方
remove_column(テーブル名, カラム名 [, 型, オプション])
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :limit | カラムの桁数を指定 | |
| :default | デフォルト値を指定 | |
| :null | NULL値を許可するか | true | 
| :precision | :decimal、:numeric、:datetime、および:time型の精度を指定 | |
| :scale | :decimal、:numeric型の小数点以下の桁数 | |
| :collation | :stringまたは;textの照合順序を指定 | |
| :comment | カラムのコメントを指定。データベース管理ツールなどで閲覧が可能 | 
precisionとscaleについては、データベースによって差があるので注意が必要
例
usersテーブルのdescriptionカラムを削除
remove_column :users, :description
カラムの桁数を指定
remove_column :users, :description, :string, limit: 20
ソースコード
複数のカラムを削除
layout: page
説明
指定したテーブルの複数のカラムを削除
使い方
remove_columns(テーブル名, カラム名 [, ...])
例
指定したテーブルの複数のカラムを削除
remove_columns(:suppliers, :qualification, :experience)
ソースコード
カラムの初期値を設定
layout: page
説明
カラムの初期値を設定
使い方
change_column_default(テーブル名, カラム名, 初期値)
例
カラムの初期値を設定
change_column_default(:suppliers, :qualification, 'new')
カラムの初期値設定を削除
change_column_default(:users, :email, nil)
ソースコード
カラムのコメントを変更
layout: page
説明
カラムのコメントを変更または削除
使い方
change_column_comment(テーブル名, カラム名, comment_or_changes)
例
カラムのコメントを変更
change_column_comment :posts, :state, from: "old_comment", to: "new_comment"
カラムのコメントを削除
change_column_comment :posts, :state, nil
ソースコード
NULL制約の追加または削除
layout: page
説明
NULL制約の追加または削除
使い方
change_column_null(table_name, column_name, null, default = nil)
例
追加
change_column_null(:users, :nickname, false)
削除
change_column_null(:users, :nickname, true)
ソースコード
テーブルのコメントを変更
layout: page
説明
テーブルのコメントの変更または削除
使い方
change_table_comment(テーブル名, コメント)
例
テーブルのコメントの変更
change_table_comment :posts, from: "old_comment", to: "new_comment"
テーブルのコメントの削除
change_table_comment :posts, nil
ソースコード
カラムが存在するかチェック
layout: page
説明
指定したテーブルにカラムが存在するかチェック
使い方
column_exists?(テーブル名, カラム名 [, 型, オプション])
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :limit | カラムの桁数を指定 | |
| :default | デフォルト値を指定 | |
| :null | NULL値を許可するか | true | 
| :precision | :decimal、:numeric、:datetime、および:time型の精度を指定 | |
| :scale | :decimal、:numeric型の小数点以下の桁数 | |
| :collation | :stringまたは;textの照合順序を指定 | |
| :comment | カラムのコメントを指定。データベース管理ツールなどで閲覧が可能 | 
例
pagesテーブルのtitleカラムが存在するか
column_exists? :pages, :title
suppliersテーブルのnameカラムのstring型が存在するか
column_exists? :suppliers, :name, :string
NULLを許可しない
column_exists?(:suppliers, :name, :string, null: false)
ソースコード
インデックスを追加
layout: page
説明
指定したテーブルにインデックスを追加
使い方
add_index(テーブル名, インデックスを付与するカラム名 [, オプション])
オプション
| オプション | 説明 | データベースの種類 | 
|---|---|---|
| :name | インデックスの名前 | 全て | 
| :unique | trueを指定するとユニークなインデックス | 全て | 
| :length | インデックスに含まれるカラムの長さ | 全て | 
| :order | ソート順 | MySQL | 
| :where | 部分インデックス | PostgreSQL、SQLite | 
| :using | 特定の方法のインデックス | PostgreSQL、MySQL | 
| :opclass | 特定の演算子クラスのインデックス | PostgreSQL | 
| :type | 特定のタイプのインデックス | MySQL | 
| :algorithm | 特定のアルゴリズムのインデックス | PostgreSQL | 
| :internal | 長さ制限をするか | false | 
例
usersテーブルのnameカラムのインデックスを作成
add_index :users, :name
ユニークなインデックスを作成
add_index :users, [:name, :employee_id], unique: true
インデックス名をつけて作成
add_index :users, [:name, :employee_id], unique: true, name: 'by_branch_name'
インデックスの長さを10に指定して作成
add_index :users, :name, name: 'by_name', length: 10
複数のキーで長さを指定
add_index :accounts, [:name, :surname], name: 'by_name_surname', length: {name: 10, surname: 15}
ソート順でインデックスを作成
add_index :accounts, [:branch_id, :party_id, :surname], order: {branch_id: :desc, party_id: :asc}
部分インデックスの作成
add_index :accounts, [:branch_id, :party_id], unique: true, where: "active"
特定の方法でインデックスを作成
add_index :developers, :name, using: 'btree'
特定の演算子クラスでインデックスを作成
add_index :developers, :name, using: 'gist', opclass: :gist_trgm_ops
特定のタイプのインデックスを作成
add_index :developers, :name, type: :fulltext
特定のアルゴリズムでインデックスを作成
add_index :developers, :name, algorithm: :concurrently
ソースコード
インデックスを変更
layout: page
説明
指定したテーブルのインデックスを変更
使い方
rename_index(テーブル名, 変更前の名前, 変更後の名前)
例
指定したテーブルのインデックスを変更
rename_index :people, 'index_people_on_last_name', 'index_users_on_last_name'
ソースコード
インデックスを削除
layout: page
説明
指定したテーブルのインデックスを削除
使い方
remove_index(テーブル名 [, オプション])
オプション
| オプション | 説明 | 
|---|---|
| :name | インデックス名 | 
| :column | カラム名 | 
| :algorithm | 特定のアルゴリズムのインデックス | 
例
usersテーブルのnameカラムのインディックスを削除
remove_index :users, :name
カラム名を指定
remove_index :accounts, column: :branch_id
カラム名を複数指定
remove_index :accounts, column: [:branch_id, :party_id]
インデックス名を指定
remove_index :accounts, name: :by_branch_party
特定のアルゴリズムのインデックスを指定
remove_index :accounts, name: :by_branch_party, algorithm: :concurrently
ソースコード
インデックスが存在するかチェック
layout: page
説明
指定したテーブルにインデックスが存在するか
使い方
index_exists?(テーブル名, カラム名 [, オプション])
オプション
| オプション | 説明 | 
|---|---|
| :name | インデックスの名前 | 
| :unique | trueを指定するとユニークなインデックス | 
| :length | インデックスに含まれるカラムの長さ | 
例
pagesテーブルのtitleカラムにインデックスが存在するか
index_exists? :pages, :title
複数カラムを指定
index_exists?(:suppliers, [:company_id, :company_type]
ユニークなインデックス
index_exists?(:suppliers, :company_id, unique: true)
インデックス名を指定
index_exists?(:suppliers, :company_id, name: "idx_company_id")
ソースコード
テーブルに指定した名前のインデックスが存在するかチェック
layout: page
説明
テーブルに指定した名前のインデックスが存在するか
使い方
index_name_exists?(テーブル名, インデックス名)
例
テーブルに指定した名前のインデックスが存在するか
index_name_exists?(:pages, :title)
ソースコード
created_atとupdated_atを生成
layout: page
説明
created_atとupdated_atを両方追加するメソッド
使い方
timestamps
例
usersテーブルにtimestampsを設定
create_table :users do |t|
  t.timestamps
end
ソースコード
タイムスタンプを追加
layout: page
説明
既存のテーブルにタイムスタンプ(created_atとupdated_at)を追加
使い方
add_timestamps(テーブル名)
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :limit | カラムの桁数を指定 | |
| :default | デフォルト値を指定 | |
| :null | NULL値を許可するか | false | 
| :precision | :decimal、:numeric、:datetime、および:time型の精度を指定 | |
| :scale | :decimal、:numeric型の小数点以下の桁数 | |
| :collation | :stringまたは;textの照合順序を指定 | |
| :comment | カラムのコメントを指定。データベース管理ツールなどで閲覧が可能 | 
例
usersテーブルにcreated_atとupdated_atを追加
add_timestamps :users
NULLを許可
add_timestamps :suppliers, null: true
ソースコード
created_atとupdated_atの削除
layout: page
説明
既存のテーブルのcreated_atとupdated_atを削除
使い方
remove_timestamps(テーブル名)
例
usersテーブルのcreated_atとupdated_atを削除
remove_timestamps(:users)
ソースコード
リファレンスを生成
layout: page
説明
既存のテーブルにリファレンスを追加
使い方
references(カラム名 [, オプション])
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :type | カラムタイプ | :bigint | 
| :index | インデックスを付与 | true | 
| :foreign_key | 外部キーの制約 | false | 
| :polymorphic | ポリモーフィックを付与 | false | 
| :null | NULLを許可するか | true | 
例
既存のテーブルにリファレンスを追加
t.references(:user)
ソースコード
リファレンスを追加
layout: page
説明
既存のテーブルにリファレンスを追加
使い方
add_reference(テーブル名, リファレンス名 [, オプション])
オプション
| オプション | 説明 | デフォルト値 | 
|---|---|---|
| :type | カラムタイプ | :bigint | 
| :index | インデックスを付与 | true | 
| :foreign_key | 外部キーの制約 | false | 
| :polymorphic | ポリモーフィックを付与 | false | 
| :null | NULLを許可するか | true | 
例
既存のテーブルにリファレンスを追加
add_reference(:products, :user)
文字列で作成
add_reference(:products, :user, type: :string)
ユニークなインデックス
add_reference(:products, :supplier, index: { unique: true })
外部キー指定
add_reference(:products, :supplier, foreign_key: true)
NULLを許可しない
add_reference(:products, :user, null: false)
ソースコード
リファレンスを削除
layout: page
説明
既存のテーブルのリファレンスを削除
使い方
remove_reference(テーブル名, リファレンス名 [, オプション])
オプション
| オプション | 説明 | 
|---|---|
| :polymorphic | ポリモーフィックを付与 | 
| :index | インデックスを付与 | 
| :foreign_key | 外部キーの制約 | 
例
既存のテーブルのリファレンスを削除
remove_reference(:products, :user, index: true)
ポリモーフィックを付与
remove_reference(:products, :supplier, polymorphic: true)
外部キーの制約を指定
remove_reference(:products, :user, foreign_key: true)
ソースコード
マイグレーションファイルでSQLを実行
layout: page
説明
マイグレーションファイルでSQLを実行
使い方
execute(SQL文)
例
pagesテーブルの最新の10件を取得
execute "SELECT * FROM pages ORDER BY updated_at DESC LIMIT 10"