删除has_many的正确方法:通过连接记录?

时间:2013-06-05 17:11:46

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

class Post < ActiveRecord::Base
  has_many :posts_tags
  has_many :tags, through: :posts_tags
end

class PostsTag < ActiveRecord::Base
  belongs_to :post
  belongs_to :tag
end

class Tag < ActiveRecord::Base
  has_many :posts_tags
  has_many :posts, through: :posts_tags
end

当Post被破坏时,我希望它的所有关联也被删除。我不想在PostsTag模型上运行验证。我只是想删除。

我发现在Post模型中添加一个依赖于帖子标签的关系可以按我的方式工作:has_many :posts_tags, dependent: :delete_all

但是,有关该主题的文档似乎建议我应该这样做:has_many :tags, through: :posts_tags, dependent: :delete_all。当我这样做时,Tag对象被破坏,连接对象仍然存在。

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many

  

对于has_many,destroy将始终调用正在删除的记录的destroy方法,以便运行回调。但是,删除将根据:dependent选项指定的策略进行删除,或者如果没有给出依赖选项,则它将遵循默认策略。默认策略是:nullify(将外键设置为nil),除has_many:through外,其中默认策略为delete_all(删除连接记录,不运行其回调)。

  1. 如何实际使用默认策略?如果我离开:完全依赖,则根本不删除任何记录。我不能只指出:依赖于has_many关系。 Rails回来说“The:dependent选项要么:destroy,:delete_all,:nullify或:restrict({})”。
  2. 如果我没有指定:依赖于任何一种关系,它不会使PostsTag对象上的post_id无效,因为它似乎暗示
  3. 也许我读错了,我找到的方法是正确的方法?

1 个答案:

答案 0 :(得分:20)

您最初的想法:

has_many :posts_tags, dependent: :delete_all

正是你想要的。你 not 想要在has-many-though关联:tags上声明这个,因为这会破坏所有相关的标签。您要删除的是关联本身 - 这是PostTag连接模型所代表的内容。

那么为什么文档说他们做了什么?您误解了文档描述的场景:

Post.find(1).destroy
Post.find(1).tags.delete

第一个电话(你的场景)将简单地破坏帖子。也就是说,除非您指定:dependent策略,否则我建议您这样做。第二个调用是文档描述的内容。调用.tags.delete不会(默认情况下)实际销毁标记(因为它们通过has-many-through连接),但是连接这些标记的关联连接模型。