LoginSignup
22
17

More than 3 years have passed since last update.

【Rails】before_destroyでmodelの削除可否チェック

Posted at

modelの削除可否チェックを実装したい

親modelが複数の子modelを持っているケースで、

parent.rb
class Parent < ActiveRecord::Base
  has_many :children, dependent: :destroy
end
child.rb
class Child < ActiveRecord::Base
  belongs_to :parent
end

ここで、子modelが0件になってしまう場合は削除できないのような削除可否チェックを挟みたい場合は、 子modelにbefore_destory で実装すると良い。

child.rb
class Child < ActiveRecord::Base
  belongs_to :parent

  # 追加
  before_destroy :must_not_destroy_last_one_child

  private

  def must_not_destroy_last_one_child
    throw(:abort) if (parent.children - [self]).empty?
  end
end

親modelごと削除したいときに子modelのbefore_destoryが邪魔になる

このままだと、親modelごと削除するときに子modelのbefore_destoryに引っかかってエラーとなってしまう。

親modelごと削除の場合は、destroyed_by_association が設定されているので、その値を見てreturnしてしまえばよい。

child.rb
class Child < ActiveRecord::Base
  belongs_to :parent

  before_destroy :must_not_destroy_last_one_child

  private

  def must_not_destroy_last_one_child
    return if destroyed_by_association.present? # 追加
    throw(:abort) if (parent.children - [self]).empty?
  end
end

これで解決:smile:

余談

親model側で、 dependent: :delete_all に変えることでActive Record コールバックを発生させないというアプローチもあるが、これはおすすめしない。

今後、子modelにコールバックが追加されたり、孫modelが増える可能性とか色々を考慮すると、不正なデータを発生させないために考えることが増えてしまうので。。

22
17
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
22
17