はじめに
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
おわり
これであなたも外部キーマスター(マイグレーションに限る)