マイグレーションでよく出てくるクラスやメソッドについて
今回はマイグレーション関連の基礎知識まとめについて書いてみます。
マイグレーションとは
そもそもマイグレーションとはデータベースのスキーマ変更の役割を担うもの。(※スキーマファイルとはマイグレーションファイルの集合です。) railsではマイグレーションの生成時に作成されるタイムスタンプ値(例:201903140739324のような)を使ってそのスクリプトが実行済みかどうかを管理します。
Railsではschema_migrationsテーブルとdb/migrateフォルダ配下のマイグレーションファイルを比較し、未実行のマイグレーションを自動的に認識し実行しています。
マイグレーション機能では特定のタイミングでスキーマの状態を戻したり、指定視されたバージョンだけスキーマをロールバックすることもできる。
メソッドの種類について
マイグレーションファイルではchange
, up
, down
などのメソッドを使います。このメソッドについて説明します。
changeメソッド
changeメソッドはスキーマ操作の実処理を表す基本です。マイグレーションを自作する場合に使います。このメソッドを使うと、Active Recordがマイグレーションを逆方向に実行(ロールバック)する方法を自動的に理解してくれるので便利な機能です。changeでサポートされているマイグレーション定義は以下。
- add_column
- addforeignkey
- add_index
- add_reference
- add_timestamps
- changecolumndefault (:fromと:toの指定は省略できない)
- changecolumnnull
- createjointable
- create_table
- disable_extension
- dropjointable
- drop_table (ブロックを渡さなければならない)
- enable_extension
- remove_column(型を指定しなければならない)
- removeforeignkey(2番目のテーブルを指定しなければならない)
- remove_index
- remove_reference
- remove_timestamps
- rename_column
- rename_index
- rename_table
up/downメソッド
upメソッドはスキーマに対する変換方法を記述し、downメソッドにはupメソッドによって行われた変換を逆転する方法を記述する必要がある。つまり、upの後にdownを実行した場合、スキーマが変更されないようにする必要がある。例えばupメソッドでテーブルを作成したら、downメソッドでテーブルを削除する必要がある。downメソッド内で行う変換の順序はupメソッドの逆になるようにする。
例
class ExampleMigration < ActiveRecord::Migration [5.0]
def up
create_table :distributors do |t|
t.string :zipcode
end
# CHECK制約を追加
execute <<-SQL
ALTER TABLE distributors
ADD CONSTRAINT zipchk
CHECK (char_length(zipcode) = 5);
SQL
add_column :users, :home_page_url, :string
rename_column :users, :email, :email_address
end
def down
rename_column :users, :email_address, :email
remove_column :users, :home_page_url
execute <<-SQL
ALTER TABLE distributors
DROP CONSTRAINT zipchk
SQL
drop_table :distributors
end
end
revertメソッド
revertメソッドはActive Recordのマイグレーションロールバック機能を利用できます。revertメソッドは逆転を行う命令を含むブロックを受け取ることができる。これは、以前のマイグレーションの一部のみを逆転したい場合に便利です。
たとえば、ExampleMigrationがコミット済みになっており、後になって郵便番号を検証するにはCHECK制約よりもActive Recordのバリデーションを使う方がよいことに気付いたとしましょう。revertを使わずに同様のマイグレーションを自作することもできますが、その分余計な手間がかかります (createtableとreversibleの順序を逆にし、createtableをdroptableに置き換え、最後にupとdownを入れ替えます)。 revertはこれらを一手に引き受けてくれます。参照: [Active Record マイグレーション](https://railsguides.jp/activerecord_migrations.html)
class DontUseConstraintForZipcodeValidationMigration < ActiveRecord::Migration[5.0]
def change
revert do
# ExampleMigrationのコードをコピー&ペースト
reversible do |dir|
dir.up do
# CHECK制約を追加
execute <<-SQL
ALTER TABLE distributors
ADD CONSTRAINT zipchk
CHECK (char_length(zipcode) = 5);
SQL
end
dir.down do
execute <<-SQL
ALTER TABLE distributors
DROP CONSTRAINT zipchk
SQL
end
end
# 以後のマイグレーションはOK
end
end
end
マイグレーションの実行について
マイグレーションをすぐに実行する場合はrails db:migrateを打ち込む。これで未実行のchangeまたはupメソッドを実行する。未実行のマイグレーションがない場合は何もせずに終了する。
ロールバック
直前に行ったマイグレーションをロールバックする場合に使う
rails db:migrate
これはchangeメソッドを逆転実行するか、downメソッドを実行する。マイグレーションを複数ロールバックする場合はSTEPパラメータを指定する。
rails db:rollback STEP=3
※ db:migrateで実行できないタスクをこれらのタスクで実行することはできません。これらは単にバージョンを明示的に指定しなくて済むようにdb:migrateタスクを使いやすくしたものに過ぎない。
データベースを設定する
rails db:setupタスクはデータベースの作成、スキーマの読み込み、シードデータを用いてデータベースの初期化を実行する。
データベースをリセットする
rails db:resetタスクはデータベースをdropして再度設定する。ちなみにこれは rails db:drop db:setupと同じ。
まとめ
今回はマイグレーションに関する内容で気になったものをメモってみました。実は今回ブログ書いた背景として友達のエンジニアにも必要な道具(知識)はそろそろ調べてから使ったほうがいいよと言われたのがきっかけです。正直これまでほぼ写経でなんとんかく進めてアプリ動いて「すげー」となってましたが、確かに次のステップに行かないとということで細かい書きました。