2

我有一个有很多孩子的模型。我是这样设置/删除孩子的:

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函数不会触发回调,所以无论如何要改变这种行为?

谢谢。

4

4 回答 4

1

delete_all正在被处决……仅仅因为?这就是 Rails 核心团队认为在这种情况下应该调用的名称。但是,您可以显式调用destroy_all模型子级的方法,但不能使用该类型的查询。看起来您是直接设置子 ID,而不是使用任何build()destroy()方法。

是的,您可以覆盖其功能。您可以修补它并将其放入 中/vendordestroy_all改用 重写相同的代码块。然后使用send命令将基本 ActiveRecord 功能替换为您自己的。

于 2010-01-12T09:54:44.787 回答
1

就像是:

mymodel.children.find([2,3]).each {|c| c.destroy }

将完成这项工作。这不完全是你想要的,但我希望它有所帮助。

于 2010-01-12T09:58:45.290 回答
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
于 2010-01-13T03:47:18.423 回答
1

我对回调有类似的问题。使用 alias_method_chain 解决了它以覆盖默认设置器。

  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/

于 2010-09-23T14:07:24.037 回答