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

时间:2012-05-15 09:30:09

标签: ruby-on-rails ruby-on-rails-3 callback has-many-through

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

由于“Automatic deletion of join models is direct, no destroy callbacks are triggered.”我无法使用回调。

在任务中,我需要所有project_ids在保存任务后计算Project的值。 如何通过关联禁用删除或更改删除以销毁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

4 个答案:

答案 0 :(得分:52)

好像我必须使用associations callbacks before_addafter_addbefore_removeafter_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   

答案 1 :(得分:1)

这就是我做的事情

在模型中:

Expressions.dateTemplate

在我的Lib文件夹中:

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

答案 2 :(得分:0)

更新联接模型关联后,Rails在集合上添加和删除记录。要删除记录,Rails使用delete方法,该方法将不会调用任何destroy callback

在删除记录时,您可以强制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 callbacks。如果您使用的是paranoia,这可能会非常有用。

答案 3 :(得分:0)

似乎将dependent: :destroy添加到has_many :through关系将破坏联接模型(而不是删除)。这是因为CollectionAssociation#delete内部引用:dependent选项来确定是删除还是销毁传递的记录。

所以在您的情况下,

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

应该工作。