※一部ガイド内容を省略したりとザックリとしたまとめを意識しているので不十分な個所があるという点をご了承ください
(reference、外部キー関連、など省略)
*都度更新していく予定です
参考&引用サイト:Active Record マイグレーション
マイグレーションの概要
*"migration"(移行)⇒「DBのテーブル作成や変更」(「状態Aから状態Bへの"移行"」みたいな意味合いを持つ)
- ActiveRecordの機能の1つ
- DBスキーマ(テーブルの定義など)を長期にわたって安定して変更など加えられるようにする仕組み
- 生のSQLを用いる必要が無い仕組みが大きな特徴と言える
- マイグレーションの度に"マイグレーションファイル"が作成される。このファイルごとを"バージョン"と見なしている
-
schema.rbという「DBに管理してもらいたいテーブル定義書」の役割を持つファイルに対して変更内容が反映されていく- 直接
schema.rbを触るのではなく、マイグレーションファイルに変更内容を記述して反映していく- これで変更のバージョン管理をしながらDBの最新状況の反映も行える
- 直接
マイグレーションの例を以下に示します。
class CreateProducts < ActiveRecord::Migration[7.1] def change create_table :products do |t| t.string :name t.text :description t.timestamps end end end
| コード箇所 | 説明 |
|---|---|
create_table :products ~ |
"products"という名前のテーブルを作成 |
t.string :name |
String型のnameカラム |
t.text :description |
text型のdescriptionカラム |
t.timestamps |
created_at、updated_atの2つのカラムを追加(自動で生成&管理してくれる) |
- SQLを書かなくてもDBへのテーブル作成&カラム変更の命令を実装できる
- 基本、マイグレーションファイルを編集してDBへ変更内容を反映する
マイグレーションを生成する
マイグレーションファイルについて
-
db/migrateディレクトリに保存 - 1つのマイグレーションファイルが1つのマイグレーションクラスに対応(1対1)
- 先述のマイグレーション例の場合、マイグレーションクラス
CreateProductsに対してマイグレーションファイルYYYYMMDDHHMMSS_create_products.rbが対応する
- 先述のマイグレーション例の場合、マイグレーションクラス
- マイグレーションファイル名は
YYYYMMDDHHMMSS_create_products.rb(YYYYMMDDHHMMSS = "西暦 月 日 時 分 秒")- YYYYMMDDHHMMSS をファイル名につけることで「実行順番が必ず最新の反映内容が採用されるようになる」「一意になる」「変更履歴がファイル名から分かる」というメリットがある
$ bin/rails generate migration AddPartNumberToProducts上を実行すると、空のマイグレーションが適切な名前で作成されます。
class AddPartNumberToProducts < ActiveRecord::Migration[7.1] def change end end
新しいカラムを追加・削除する
- マイグレーション時、コマンドに適切な引数を渡せば生成されるファイルに自動で中身に記述も加えてくれる
※"AddColumnToTable"、"RemoveColumnFromTable"をそのまま入力するのではなく以下のように書き換えるということ
| コマンド | マイグレーション内容 |
|---|---|
Add(追加したいカラム名)To(追加先テーブル) |
カラムの追加 |
Remove(削除したいカラム名)From(削除先テーブル) |
カラムの削除 |
マイグレーション名が"AddColumnToTable"や"RemoveColumnFromTable"で、かつその後ろにカラム名や型が続く形式になっていれば、適切なadd_column文やremove_column文を含むマイグレーションが作成されます。
$ bin/rails generate migration AddPartNumberToProducts part_number:string上を実行すると以下のマイグレーションファイルが生成されます。
class AddPartNumberToProducts < ActiveRecord::Migration[7.1] def change add_column :products, :part_number, :string end end
⇒add_column :products, :part_number, :stringの部分は自動で追加した上でファイル生成してくれる
【構文】
$ bin/rails generate migration Add(カラム名)To(テーブル名) (カラム名1):(データ型1) (カラム名2):(データ型2) ... (カラム名N):(データ型N)
$ bin/rails generate migration Remove(カラム名)From(テーブル名) (カラム名1):(データ型1) (カラム名2):(データ型2) ... (カラム名N):(データ型N)
※AddColumnToTableのColumnに関しては任意の文字列でも問題ないという旨が確認される ← (未検証なので検証必要)
(AddColumnToTableのTableおよびRemoveColumnFromTableは不可) ← (これも未検証なので検証必要)
新しいテーブルを作成する
- テーブルの作成は
Create(テーブル名)で指定する(要領はカラムの時と同じ)
$ bin/rails generate migration CreateProducts name:string part_number:string
上を実行すると以下のマイグレーションファイルが生成されます。class CreateProducts < ActiveRecord::Migration[7.1] def change create_table :products do |t| t.string :name t.string :part_number t.timestamps end end end
【構文】
$ bin/rails generate migration Add(カラム名)To(テーブル名) (カラム名1):(データ型1) (カラム名2):(データ型2) ... (カラム名N):(データ型N)
テーブル・カラムの変更
- 既存のテーブルおよびカラムに対して変更も可能
-
ALTER TABLE...と同等の作用
-
#以下、ガイドより引用したテーブルの変更サンプル)
change_table :products do |t| t.remove :description, :name t.string :part_number t.index :part_number t.rename :upccode, :upc_code end
| 詳細 | |
|---|---|
| t.remove :description, :name |
productsテーブルのdescription,nameカラムを削除 |
| t.string :part_number |
productsテーブルにpart_numberを追加 |
| t.index :part_number |
productsテーブルのpart_numberにインデックスを追加 |
| t.rename :upccode, :upc_code |
productsテーブルのupccodeカラム名をupc_codeに変更 |
#以下、ガイドより引用したカラムの変更サンプル
change_column :products, :part_number, :text
| 詳細 | |
|---|---|
| change_column :products, :part_number, :text |
productsテーブルのpart_numberカラムのデータ型をtextに変更 |
マイグレーションの実行&ロールバック
- 基本
rails db:migrateでマイグレーションファイルの内容に従って実行される- まだ実行されていない
def changeを実行する。(本記事では省略したupメソッドも対象) - 未実行のマイグレーションがない場合は何もせずに終了
-
rails db:migrateを何回実行しても実害はないという事なので、「あれ?このマイグレーションファイルって実行したっけ?」という状況になったら確認の意味でも実行してするのもOK
-
- マイグレーションの実行順序は、マイグレーションの日付が基準になります
- これがマイグレーションファイル名を
YYYYMMDDHHMMSS_create_products.rbとする理由
- これがマイグレーションファイル名を
- まだ実行されていない
- ロールバックは
$ bin/rails db:rollback- マイグレーション実行はされていない。前の適用内容は取り消したよという状態
-
$ bin/rails db:migrate:redoのコマンドではロールバックしてからマイグレーション実行-
$ bin/rails db:rollback && bin/rails db:migrateと同等
-
【構文】
rails db:migrate:最新のマイグレーションファイルの内容に従って実行
bin/rails db:rollback:最後に適用したマイグレーションファイルから1つロールバック(マイグレーションは未実行)
-
YYYYMMDDHHMMSSがバージョンの意味を持つので$ bin/rails db:migrate VERSION=YYYYMMDDHHMMSSと引数を渡すと「そのバージョンまでを実行する」といった指定実行を可能にしている - ロールバックも同様に「最新マイグレーション適用時点から何個前に遡るか」を
STEP=(バージョンダウンする数)で渡すことが可能。bin/rails db:rollback STEP=3とすると「最後に適用したマイグレーションから"3"つ前のマイグレーションにロールバックする」といった指令実行になる
*なんとなく「ファイル名に作成時刻を入れてる」な程度の認識でいたが、"YYYYMMDDHHMMSS"はバージョンとしての意味合いが強い点は留意すべき
スキーマダンプの意義
*「schema.rbというファイルは必要あるの?」という章
>基本schema.rbを直接触らないのに何でファイルとして置いておくのか
- 「DBのマイグレーション適用状況が
schema.rbから分かる」から- より砕くと「何か色々とマイグレーションファイルを作って実行してきたが、現状はどんな感じでスキーマが構築されているんだろう?」という時にマイグレーションファイルを1つ1つログのように辿るのではなく、スキーマファイルを確認して最終的なマイグレーションの反映状況を把握するのに役立つ
-
schema.rbは自分のマイグレーション反映状況を把握できる情報源