为什么没有收集= has_many上的对象:通过删除关联时连接模型上的触发器回调?

时间:2015-11-25 03:17:11

标签: ruby-on-rails ruby-on-rails-4 activerecord callback has-many-through

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

  

collection=objects删除和替换馆藏内容   适当添加对象。如果:through选项为true   除了destroy回调之外,触发连接模型中的回调,   因为删除是直接的。

幸运的是,它至少记录在案,但我想知道为什么到底是这样的?希望有技术原因,否则它只是疯了!

在我的情况下,我在连接表模型上有一个has_and_belongs_to_many关系到另一个模型。删除第一个连接表上的关联记录时,永远不会删除该第二个连接表上的记录。我采取了这种感觉很难的,我必须在: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

确认'确认'两个外键之间的连接表记录的唯一性,这就是为什么我可以在回调中调用first的原因。

2 个答案:

答案 0 :(得分:2)

通常,如果您想通过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

当对象被销毁时,它会在每个提供了destroy依赖的对象上调用destroy。因此User会在每个Partnership上调用destroy,并且每Partnership次调用都会在每个Partner上进行销毁。

“为什么它不能与through一起使用” - 答案是“因为删除是直接的”。我知道它并没有说太多(对我来说也是如此),但另一方面,对于我来说,将依赖项添加到没有直接链接的对象是一个坏主意。 考虑上面的例子:如果依赖 - destroy将对合作伙伴起作用并销毁它们 - 它是否也会破坏连接模型?肯定是的,因为在其他情况下它会导致数据损坏,但是你可能会丢失一些可能存在于连接模型中的数据,所以在某些情况下 - 不,你不想破坏连接模型。这意味着Rails团队必须添加新参数 - delete_join以指示您是否要保存该模型。 这只是一个糟糕的设计,因为我们已经有了更好的方法 - 在连接模型中添加依赖关系。

答案 1 :(得分:1)

所以前几天我遇到了同样的问题。 在我的情况下,我正在做类似于你正在做的事情,并且遇到了同样的问题,连接表被删除而不是被破坏。

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

您需要做的就是将依赖::: 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.

依赖::破坏合作伙伴关系固定的那个。回调现在正在运行,事情又好了。