Railsの外部キー制約

外部キー制約とは

関連付ける2つのテーブルの間でデータの整合性を保つための制約(約束事)。
制約として以下の2つがある。

  • 親テーブルの指定したデータ以外は、子テーブルの外部キーとして登録できない
  • 親テーブルのデータを削除しようとしたときに、そのデータが子テーブルに外部キーとして使われている場合は親テーブルのレコードを削除できない

メリット

  • データの整合性を保てる
  • 誤って親テーブルのデータを消すことを防げる

外部キー制約のついたカラムの作成方法

テーブル作成時にreference型で foreign_key: ture を付けてカラムを作成する。

マイグレーションファイルを作成して以下のように記述。
(例:user:task の関係が 1:N )

  def change
    create_table :tasks do |t|
      t.string    :name
      t.text      :description
      t.references :user, foreign_key: true
    end
  end

この記述でTaskテーブルには以下のカラムが作成される。

  • name
  • description
  • user_id → 外部キー制約が付いている

外部キー制約の付いたカラムを追加したい場合は、マイグレーションファイルを作成して以下を記述。

def change
  add_reference :tasks, :user, foreign_key: true
end

注意すること

メリットでもあるが、外部キー制約を付けると子テーブルが外部キーとして参照している親テーブルのレコードは削除できない。

一番簡単な解決方法としては、親テーブルのモデルに dependent オプションで:destroyを指定すれば良い。

class User < ApplicationRecord
  has_many :tasks, dependent: :destroy
end   

この場合、親テーブルを削除すると関連付けられた子テーブルも全て削除される。

dependent オプションには他にも、

  • :nullify → 親テーブルのみ削除して、子テーブルの外部キーカラムにはnullを入れる
  • :restrict_with_error → 削除をせずエラーメッセージを表示させる
  • :restrict_with_exception → 削除せず例外を発生させる

などがある。

参考

railsguides.jp