22
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 被销毁时,我希望它的所有关联到 Tag 也被删除。我不想在 PostsTag 模型上运行验证。我只想删除。

我发现添加依赖关系到 Post 模型中的帖子标签可以按我的意愿工作:has_many :posts_tags, dependent: :delete_all.

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

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

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

  1. 我怎样才能实际使用默认策略?如果我完全离开 :dependent ,则根本不会删除任何记录。而且我不能只指出:依赖于 has_many 关系。Rails 回来说“:dependent 选项需要 :destroy、:delete_all、:nullify 或 :restrict ({})”。
  2. 如果我没有指定:依赖于任何一个关系,它不会像它似乎暗示的那样使 PostsTag 对象上的 post_id 无效

也许我读错了,我发现的方法是正确的方法?

4

1 回答 1

24

Your original idea of:

has_many :posts_tags, dependent: :delete_all

is exactly what you want. You do not want to declare this on the has-many-though association :tags, as that will destroy all associated Tags. What you want to delete is the association itself - which is what the PostTag join model represents.

So why do the docs say what they do? You are misunderstanding the scenario that the documentation is describing:

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

The first call (your scenario) will simply destroy the Post. That is, unless you specify a :dependent strategy, as I suggest you do. The second call is what the documentation is describing. Calling .tags.delete will not (by default) actually destroy the tags (since they are joined by has-many-through), but the associated join model that joins these tags.

于 2013-06-05T20:51:15.093 回答