【问题标题】:Why does ActiveRecord has_many use delete_all instead of destroy_all?为什么 ActiveRecord has_many 使用 delete_all 而不是 destroy_all?
【发布时间】:2010-01-12 09:34:06
【问题描述】:

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

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

谢谢。

【问题讨论】:

    标签: ruby-on-rails activerecord associations has-many


    【解决方案1】:

    类似:

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

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

    【讨论】:

    • 我想我可以重写模型类中的 children_ids= 函数,并在那里处理它......但我希望有一种更清洁/更干燥的方式。
    【解决方案2】:

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

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

    【讨论】:

    • 我想我可以只修补处理这个问题的代码。知道它住在哪里吗?
    【解决方案3】:

    对于那些感兴趣的人,我添加了以下猴子补丁来强制 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
    

    【讨论】:

    • 这个解决方案在 Rails 3.1.1 中仍然有效吗?它对我不起作用,得到wrong number of arguments (2 for 1)
    • 我不确定...我计划在几个月内将我的应用程序升级到 Rails 3.1。我想到那时我必须弄清楚这一点。
    【解决方案4】:

    我有类似的回调问题。使用 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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 2016-09-18
      • 1970-01-01
      相关资源
      最近更新 更多