2019/08/30

モデルのdependentオプションは片方にしか貼ってはいけないよという話

こんにちは、宇賀神です。
今回は久々にRailsのお話。

前提

以下のような形のモデルがありまして、 Parent1 または Parent2 のレコードを消した時に、関連するレコードも同時に消したいなぁと思って dependent オプションを設定した時です。

class Parent1 < ApplicationRecord
  has_many :child, dependent: :destroy
end

class Parent2 < ApplicationRecord
  has_many :child, dependent: :destroy
end

class Child < ApplicationRecord
  belongs_to :parent1, dependent: :destroy
  belongs_to :parent2, dependent: :destroy
end

何があった

この状態で parent1.destroy! などを実行すると以下のようになって削除が失敗します。

1. parent1.destroy!
2. Parent1 が Child を消しにいく
3. Child が Parent2 を消しにいく
4. Parent2 が Child を消しにいく

以下3〜4で無限ループ

対策

そもそも子から親に対してdependentオプションを設定するのはバッドパターンぽいので基本的にやめましょう。横着してはいけません(教訓)。

また更新します〜〜