DBに制約を追加するときのお作法
はじめに
DBに nil: false
などの制約を追加するとき、制約のことを何と呼ぶのか、どのように変更を加えるのが良いのかを調べたり聞いたりしたことをまとめています。
1. なんと呼ぶのか
最初、制約の部分をなんと呼ぶのかわからず、「nil: false, rails」みたいなキーワードでしか情報を得られずにいました…。
2. どのように変更を加えるのが良いのか
ここからは、DBに制約を加える場合、と言うよりかは制約に限らずmigrationに変更を加える際に共通して言えることです。
(1) migrateファイルを作成する
migrationに変更を加える際は、既存のマイグレーションを編集するのではなく、新しいマイグレーションファイルを生成します。
なぜ新たに作る必要があるのか?
なぜ新しいマイグレーションファイルを作成する必要があるのか?
コミット履歴から追えるのでは?
と最初は思ったのですが、下記のような点から…
- マイグレーション名を指定することで、そのクラス内でどういう意図の変更が行われたかが明確になる
- デプロイ済みの場合は、どのバージョンまでが本番環境で、どのバージョンからが開発環境なのかが明確になる
- クラス単位で簡単にrollbackできる
メンテナンス性を考えて、「好ましい」というよりは「特別な事情が無い限りまずそうすべき」と思う方が良さそうです。
新しいマイグレーションのクラス名はどうすればいいのか
マイグレーションに対して、何にどういう変更を加えているかがわかるように命名します。
例)パート番号をUserモデルに追加する
$ rails generate migration AddPartNumberToUsers
例)IndexをTaskモデルに追加する
$ rails generate migration AddIndexToTasks
※マイグレーション名と言っていますが、これはクラス名のため、同じ名前を設定することができません。重複する場合は、必要に応じて番号を付与するなどの管理が必要があります。
(2) redoで確認を行う
DBに変更を加えてmigrateする際に、rails db:migrate:redo
を行います。
redoは何をしてくれるのか
指定したmigrationファイルのself.downメソッドを実行
してくれます。
実際に、create_table :interviews do …
ようなmigrationファイルに対してrails db:migrate:redo
を実行すると、
$ rails db:migrate:redo == 20180324060208 CreateInterviews: reverting ================================= -- drop_table(:interviews) -> 0.0550s == 20180324060208 CreateInterviews: reverted (0.0592s) ======================== == 20180324060208 CreateInterviews: migrating ================================= -- create_table(:interviews) -> 0.3552s == 20180324060208 CreateInterviews: migrated (0.3553s) ========================
このように、まずreverting
でdrop_table(:interviews)
が実行されてから、migrating
でcreate_table(:interviews)
が実行されていることがわかります。
つまり、rollback(前のバージョンに戻すこと)が必要になった場合にdbを破壊することなく正常に実施できることをここで確認できるのです。
いつもそうすべきなのか
いつも、rails db:migrate:redo
を行うよう癖付けておくと確認漏れを防げて良いです。
例えば、DBに変更を加える前のブランチを触る場合や複数人で開発を行う際に、rollbackできない変更があるとDBを破壊してしまうリスクが大きくなってしまいます。いつも、rails db:migrate
だとそのリスクに気がつかない可能性がありますが、いつもrails db:migrate:redo
だとチェックが出来ている状況を保てます。
参照
rake db:migrate - リファレンス - - Railsドキュメント Ruby - railsのmigrationについて質問です(46853)|teratail