为什么 collection=objects on has_many :through 在删除关联时触发连接模型上的回调?

Why doesn't collection=objects on has_many :through trigger callbacks on the join model on deletion of the association?

Rails 4 文档说明了关于 has_many :through 关系的连接模型上的销毁回调:

collection=objects Replaces the collections content by deleting and adding objects as appropriate. If the :through option is true callbacks in the join models are triggered except destroy callbacks, since deletion is direct.

谢天谢地,至少有文档记录,但我想知道到底为什么会这样?希望有技术原因,否则就太疯狂了!

在我的例子中,我在将 table 模型连接到另一个模型时有一个 has_and_belongs_to_many 关系。当第一个连接 table 上的关联记录被删除时,第二个连接 table 上的记录将永远不会被删除。我采用了这个感觉很老套的方法,我必须在 :through 关系的每一边重复一遍:

has_many :schools_templates, dependent: :destroy
has_many :templates, through: :schools_templates, before_remove: :remove_groups_school_templates

private

def remove_groups_school_templates(template)
  schools_templates.where(template: template).first.groups.clear
end

在两个外键之间的连接 tables 记录上有 'ensure' 唯一性验证,所以这就是我可以在回调中调用 first 的原因。

通常,如果您想通过 has_many 关联删除某些内容,您可以将 dependent: :destroy 放在那里:

class User
  has_many :partnerships, dependent: :destroy
  has_many :partners, through: :partnerships
end

如果你想破坏 partners 以及伙伴关系,你必须将此依赖项添加到 Partnership 模型:

class Partnership
  belongs_to :partner, dependent: :destroy
  belongs_to :user
end

当对象被销毁时,它会在每个提供销毁依赖项的对象上调用销毁。所以 User 在每个 Partnership 上调用销毁,并且每个 Partnership 在每个 Partner.

上调用销毁

"Why it can not be used with through" - 嗯,答案是 "since deletion is direct"。我知道它并没有说明什么(对我来说),但另一方面,对我来说,向没有直接链接的对象添加依赖项是一个坏主意。 考虑上面的例子:如果依赖 - destroy 将对合作伙伴起作用并销毁它们 - 它是否也应该销毁连接模型?当然是的,因为在其他情况下它会导致数据损坏,但您可能会丢失一些可能位于连接模型中的数据,所以在某些情况下 – 不,您不想破坏连接模型。这意味着 Rails 团队必须添加新参数 – delete_join 以指示您是否要保存该模型。 这只是一个糟糕的设计,因为我们已经有了更好的方法——在连接模型中添加依赖关系。

所以前几天我 运行 遇到了同样的问题。 在我的例子中,我正在做一些类似于你正在做的事情,并且 运行 遇到了同样的问题,连接 table 被删除而不是被销毁。

我开始查看代码,我认为文档已经过时了。 has_many_through_association

您需要做的就是将 dependent: :destroy 添加到 has_many :through 关系中。

class User
  has_many :partnerships, dependent: :destroy
  has_many :partners, through: :partnerships, dependent: :destroy
end

我正在处理的痛苦是:

user.partner_ids = [1,2,3]
#creates the relationships
user.partner_ids = []
#was deleting the records from partnerships without callbacks.

合作伙伴关系上的 dependent: :destroy 解决了这个问题。现在正在回调 运行,情况又好了。