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

Bri*_*ian 16 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
Run Code Online (Sandbox Code Playgroud)

当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无效,因为它似乎暗示

也许我读错了,我找到的方法是正确的方法?

Pin*_*nyM 20

你原来的想法:

has_many :posts_tags, dependent: :delete_all
Run Code Online (Sandbox Code Playgroud)

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

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

Post.find(1).destroy
Post.find(1).tags.delete
Run Code Online (Sandbox Code Playgroud)

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

  • @MSC `Tag.where(id: @post.tags).delete_all` 可能是最简单的方法 (2认同)