如何通过关联在 has_many 中使用回调?

问题描述 投票:0回答:4

我有一个通过 has_many 关联到项目模型的任务模型,需要在通过关联删除/插入之前操作数据。

因为“连接模型的自动删除是直接的,没有触发销毁回调。”我不能为此使用回调。

在任务中,我需要所有 project_ids 来计算保存任务后项目的值。 我如何通过关联禁用删除或更改删除以在 has_many 上销毁? 这个问题的最佳实践是什么?

class Task
  has_many :project_tasks
  has_many :projects, :through => :project_tasks

class ProjectTask
  belongs_to :project
  belongs_to :task

class Project
  has_many :project_tasks
  has_many :tasks, :through => :project_tasks
ruby-on-rails ruby-on-rails-3 callback has-many-through
4个回答
64
投票

似乎我必须使用associations回调

before_add
after_add
before_remove
after_remove

class Task
  has_many :project_tasks
  has_many :projects, :through => :project_tasks, 
                      :before_remove => :my_before_remove, 
                      :after_remove => :my_after_remove
  protected

  def my_before_remove(obj)
    ...
  end

  def my_after_remove(obj)
    ...
  end
end   

2
投票

这就是我做的

在模型中:

class Body < ActiveRecord::Base
  has_many :hands, dependent: destroy
  has_many :fingers, through: :hands, after_remove: :touch_self
end

在我的 Lib 文件夹中:

module ActiveRecord
  class Base
  private
    def touch_self(obj)
      obj.touch && self.touch
    end
  end
end

1
投票

更新加入模型关联,Rails 添加和删除集合上的记录。要删除记录,Rails 使用

delete
方法,这个方法不会调用任何 destroy 回调

您可以强制 Rails 在删除记录时调用

destroy
而不是
delete
。 为此,安装 gem replace_with_destroy 并将选项
replace_with_destroy: true
传递给 has_many 协会。

class Task
  has_many :project_tasks
  has_many :projects, :through => :project_tasks,
            replace_with_destroy: true
  ...
end

class ProjectTask
  belongs_to :project
  belongs_to :task

  # any destroy callback in this model will be executed
  #...

end

class Project
  ...
end

有了这个,您可以确保 Rails 调用所有destroy 回调。如果您正在使用paranoia,这可能非常有用。


0
投票

似乎将

dependent: :destroy
添加到
has_many :through
关系会破坏连接模型(而不是删除)。这是因为 CollectionAssociation#delete 在内部引用
:dependent
选项来确定传递的记录是否应该被删除或销毁。

所以在你的情况下,

class Task
  has_many :project_tasks
  has_many :projects, :through => :project_tasks, :dependent => :destroy
end

应该工作。

© www.soinside.com 2019 - 2024. All rights reserved.