我有这样的情况:
class Shop < ActiveRecord::Base
has_many :services, dependent: :destroy
end
class Service < ActiveRecord::Base
has_many :model_weeks, dependent: :destroy
end
class ModelWeek < ActiveRecord::Base
before_destroy :prevent_destroy, if: :default?
private
def prevent_destroy
false
end
end
当我试图销毁一家商店时,我得到ActiveRecord::RecordNotDestroyed: Failed to destroy the record
,因为它首先开始销毁相关的记录,并且它被模型周期中的回调阻止了。
我可以在销毁商店时轻松取消设置ModelWeek的默认设置,只有当我能抓住它时。 before_destroy
模型中的Shop
在引发上述异常之前不会被触发。
那么,有没有办法在Shop模型中捕获这个,或者如果没有,是否有可能&#34;知道&#34;在ModelWeek中,父母是否触发了破坏?我调查解析调用者,但它没有提供任何有用的东西,反正它会很麻烦......
答案 0 :(得分:1)
经过一些研究和测试,这就是我想出来的:
这是调用方法的顺序(do_before_destroy
是before_destroy
回调中指定的任何方法):
所以,我可以在父母的破坏方法(Shop)中处理任何阻止儿童(ModelWeek)破坏的事情:
# Shop
def destroy
# default is a scope
ModelWeek.default.where(service_id: self.services.pluck(:id)).each do |m|
m.unset_default
end
super
end
之后没有任何东西可以阻止孩子的破坏,而且连锁店继续不受欢迎。
更新
有更好,更清晰的解决方案,无需覆盖父级的destroy
并进行任何查询:
class Shop < ActiveRecord::Base
has_many :services, dependent: :destroy, before_remove: :unset_default_week
private
def unset_default_week(service)
service.model_weeks.default.unset_default
end
end
答案 1 :(得分:0)
由于rails有从相关孩子到父母的破坏链,这真的很有道理,对吧?为了方便起见,我们可以在ModelWeek中覆盖destroy方法,如下所示:
class ModelWeek < ActiveRecord::Base
# before_destroy :prevent_destroy, if: :default?
def destroy
unless default?
super
end
end
end
答案 2 :(得分:0)
我通过使用有趣的黑客来解决这个问题,
你只需要放before_destroy
行
在关联线之前
并且在删除关联之前它将运行before_destroy