为什么ActiveRecord has_many使用delete_all而不是destroy_all?

发布于 2024-08-18 02:25:08 字数 388 浏览 5 评论 0原文

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

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 函数不会触发回调,那么有没有办法改变这种行为呢?

谢谢。

I have a model which has many children. I was setting/removing the children as such:

mymodel.children_ids = [1,2,3]
mymodel.save #add the children
mymodel.children_ids = [1]
mymodel.save #remove children 2,3

This works just fine, but I just realized that none of the callbacks (i.e. after_destroy) are not being called on the children model.

After some digging, it turns out that the delete_all function is being executed, rather than destroy_all. As the docs correctly state, the delete_all function does not fire off the callbacks, so is there anyway to change this behavior?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

挖个坑埋了你 2024-08-25 02:25:08

比如:

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

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

Something like:

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

will do the job. It's not exactly what you wanted, but I hope it helps.

撩人痒 2024-08-25 02:25:08

delete_all 正在执行...只是因为? Rails 核心团队认为在这种情况下应该这样称呼。但是,您可以对模型的子项显式调用 destroy_all 方法,但不使用该类型的查询。看起来您是直接设置子 ID,而不是使用任何 build()destroy() 方法。

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

delete_all is being executed... just because? That's what the Rails core team thought should be called in that instance. However, you could explicitly call the destroy_all method on the model's children, but not using that type of query. It looks like you're setting the child IDs directly, not using any build() or destroy() methods.

Yes, you can overwrite its functionality. You could patch it and put it in /vendor, rewriting the same block of code with destroy_all instead. Then use a send command to replace the base ActiveRecord functionality with your own.

倦话 2024-08-25 02:25:08

对于那些感兴趣的人,我添加了以下 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

For those interested, I added the following monkeypatch to force the has_many through to perform a destroy_all, rather than delete_all. There might be a better way, so I'm open to suggestions.

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
温馨耳语 2024-08-25 02:25:08

我在回调方面也遇到了类似的问题。使用 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/

I had similar problem with callbacks. Solved it using alias_method_chain to override default 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

More details on alias_method_chain:

http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文