はじめに
t.references による外部キーの設定はあまり好きでないので、この記事には記載しない。
add_foreign_key remove_foreign_keyの使い方について書く。
前提条件
User と Post モデルが存在する。
関係は 1 対 N
単純にIDでやる場合
Post の user_id → User の id
add_foreign_key :posts, :users
カラム名が異なる場合
なぜか User が code なるカラムを持っていて、Post の user_code から外部キー制約を貼りたい、そんな時。
add_foreign_key :posts, :users, column: :user_code, primary_key: :code
column で子のカラム、primary_key で親のカラムを指定する
親のレコードを消したときの挙動を変えたい (on_delete, on_update)
デフォルトだと、外部キー制約を設定した場合、子のレコードが存在していると親のレコードを削除できません。
これを restrict 設定といいます。
親のレコードが消えた時、子のレコードを同時に削除したい場合、cascade
親のレコードが消えた時、子の外部キー制約を設定したカラムを null にしたい場合は nullify に設定する必要があります。
migration から設定する方法は↓
add_foreign_key :posts, :users, on_delete: :cascade
on_update といって、親レコードの該当カラムを変更した場合の挙動も設定できます。
こちらもデフォルトだと restrict で、更新するとエラーになります。
外部キー制約を削除する
単純パターン
remove_foreign_key :posts, :users
カラム名変えて作った場合
remove_foreign_key :posts, column: :user_code
この場合、 rails db:rollbackがコケます。
再度作り直そうにもテーブルわからんぞ〜〜〜とRailsに言われます。
安定択として、migration ファイル作成時に up downを使って明示的にrollbackの処理を書いてあげると良いでしょう
def up
remove_foreign_key :posts, column: :user_code
end
def down
add_foreign_key :posts, :users, column: :user_code, primary_key: :code, on_delete: :cascade
end
おわり
これであなたも外部キーマスター(マイグレーションに限る)