Posted at

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


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が増える可能性とか色々を考慮すると、不正なデータを発生させないために考えることが増えてしまうので。。