18
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails の migration で外部キー制約の設定をする (add_foreign_key, remove_foreign_key)

Last updated at Posted at 2020-05-04

はじめに

t.references による外部キーの設定はあまり好きでないので、この記事には記載しない。
add_foreign_key remove_foreign_keyの使い方について書く。

前提条件

UserPost モデルが存在する。
関係は 1 対 N

単純にIDでやる場合

Postuser_idUserid

add_foreign_key :posts, :users

カラム名が異なる場合

なぜか Usercode なるカラムを持っていて、Postuser_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の処理を書いてあげると良いでしょう

example_migration
  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

おわり

これであなたも外部キーマスター(マイグレーションに限る)

18
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?