【问题标题】::dependent => :delete on belongs_to doesn't delete owner object:dependent => :delete on belongs_to 不会删除所有者对象
【发布时间】:2012-09-17 11:55:17
【问题描述】:

我一直在检查 belongs_to 方法的选项并在 Rails 3.2.7 中测试以下行为

根据上面的链接,:dependent 选项指出

如果设置为 :destroy,则关联的对象在执行此操作时被销毁 对象是。如果设置为 :delete,则删除关联的对象而不 调用它的destroy方法。

据我了解,如果在以下情况下删除帖子,则应删除作者:

class Post < ActiveRecord::Base
  belongs_to :author, :dependent => :delete
end

class Author < ActiveRecord::Base
  attr_accessible :name
  has_one :post

  before_destroy :log_author_removal

  private
    def log_author_removal
      logger.error('Author is getting removed')
    end

end

在控制台中:

> Post.first
  Post Load (0.4ms)  SELECT "posts".* FROM "posts" LIMIT 1
 => #<Post id: 5, title: "Post 5", author_id: 3>
> p.delete
  SQL (197.7ms)  DELETE FROM "posts" WHERE "posts"."id" = 5
 => #<Post id: 5, title: "Post 5", author_id: 3> 
> Author.find(3)
  Author Load (0.5ms)  SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT 1  [["id", 3]]
 => #<Author id: 3, name: "Author 3"> 

但是调用p.destroy 会删除相关作者。

我是否误解了上面引用的陈述?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord


    【解决方案1】:

    是的,调用delete 通常会跳过您或 rails 在销毁记录时设置的所有回调。其中包括像before_destroy 这样的回调以及销毁相关记录。

    因此,如果您调用p.delete,它不会对相关记录执行任何操作。

    当您致电p.destroy 时,它会:

    1. 调用before_destroy 回调(如果已设置)。
    2. 删除对象。
    3. 如果您设置:dependent =&gt; :delete,它将简单地删除作者对象。如果您将其设置为:destroy,它将为作者对象重复整个过程(如果适用,回调并销毁其相关记录)。
    4. 调用after_destroy 回调(如果已设置)。

    【讨论】:

    • 谢谢雅库布。根据第 3 点,应该删除作者对象,但实际上并非如此。这就是为什么我在这里发布以获取社区的意见
    • @AmitPatel 是的,但你没有打电话给destroy,你打电话给delete
    • 这意味着delete 不会对关联对象产生任何影响,无论为:dependent 设置了什么。
    【解决方案2】:

    据我了解:

    如果您在对象上调用destroy:dependent =&gt; :destroy 将触发association.destroy

    如果您在对象上调用destroy:dependent =&gt; :delete 将触发association.delete

    在这两种情况下,您都必须在父对象上调用destroy。不同之处在于子对象上调用的方法。如果您不想在子对象上触发销毁过滤器,请使用:dependent =&gt; :delete。如果您确实需要它们,请使用:dependent =&gt; :destroy

    在这里快速查看源代码:https://github.com/rails/rails/blob/357e288f4470f484ecd500954fd17fba2512c416/activerecord/lib/active_record/associations/builder/belongs_to.rb#L68

    我们看到调用dependent 只会在父模型上创建一个after_destroy,在子对象上调用deletedestroy。但在这两种情况下,它都会创建一个after_destroy

    【讨论】:

    • 谢谢。你的答案看起来更清晰。
    【解决方案3】:

    belongs_to 关联支持 :delete:destroy 用于 :dependent。 你可以参考下面的链接 http://apidock.com/rails/v4.0.2/ActiveRecord/Associations/ClassMethods/belongs_to

    调用 delete 会跳过所有回调,例如 before_destroy,也不会删除关联对象的关联记录。

    例子

    class Order < ActiveRecord::Base
    has_one :project, :dependent => :delete
    has_many :resources, :dependent => :delete
    end
    
    class Project < ActiveRecord::Base
    belongs_to :order, :dependent => :delete
    end
    

    在上面的代码中,如果项目已经被销毁,那么订单也会被删除,但订单中的资源不会被删除 但是如果我们使用

    belongs_to :order, :dependent => :destroy
    

    然后与订单相关的资源以及项目销毁时删除。

    【讨论】:

      【解决方案4】:
       belongs_to :author, :dependent => :delete
      

      应该是: belongs_to :author, :dependent => :destroy

      :destroy 和 :delete 在 ActiveRecord 中的行为不同,删除绕过验证和 AR 关联,因此关联的对象不会被删除。

      【讨论】:

      • 应该使用删除还是销毁是另一回事。我只是想了解是否应该按照语句删除关联记录如果设置为:delete,则删除关联对象而不调用其destroy方法
      【解决方案5】:

      belongs_to 关联不支持 :delete:depedent。它仅支持 :destroy。请参考此链接http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

      【讨论】:

      • 我找不到任何声明 belongs_to 关联不能支持 :delete for :dependent。
      猜你喜欢
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 1970-01-01
      • 2014-07-29
      • 2022-01-23
      相关资源
      最近更新 更多