我有一个有很多孩子的模特。我正在设置/删除孩子:
mymodel.children_ids = [1,2,3]
mymodel.save #add the children
mymodel.children_ids = [1]
mymodel.save #remove children 2,3
这很好用,但我刚才意识到没有回调(即after_destroy
)没有在子模型上调用。
经过一番挖掘,结果发现delete_all
函数正在执行,而不是destroy_all
。正如文档正确陈述的那样,delete_all
函数不会触发回调,所以无论如何都要改变这种行为?
感谢。
答案 0 :(得分:1)
delete_all
正在执行......只是因为?这就是Rails核心团队在该实例中应该调用的内容。但是,您可以在模型的子项上显式调用destroy_all
方法,但不能使用该类型的查询。您似乎直接设置子ID,而不是使用任何build()
或destroy()
方法。
是的,您可以覆盖其功能。您可以对其进行修补并将其放入/vendor
,然后使用destroy_all
重写相同的代码块。然后使用send
命令将基本ActiveRecord功能替换为您自己的功能。
答案 1 :(得分:1)
类似的东西:
mymodel.children.find([2,3]).each {|c| c.destroy }
将完成这项工作。这不完全是你想要的,但我希望它有所帮助。
答案 2 :(得分:1)
对于那些感兴趣的人,我添加了以下monkeypatch来强制has_many执行destroy_all,而不是delete_all。可能有更好的方法,所以我愿意接受建议。
module ActiveRecord
module Associations
class HasManyThroughAssociation < HasManyAssociation
def delete_records(records)
klass = @reflection.through_reflection.klass
records.each do |associate|
klass.destroy_all(construct_join_attributes(associate)) #force auditing by using destroy_all rather than delete all
end
end
end
end
end
答案 3 :(得分:1)
我遇到类似的回调问题。使用alias_method_chain解决了它,以覆盖默认的setter。
def product_categories_with_destroy=(product_categories)
unless new_record?
(self.product_categories - product_categories).each(&:destroy)
end
self.product_categories_without_destroy = product_categories
end
alias_method_chain :product_categories=, :destroy
有关alias_method_chain的更多详情:
http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/