ruby-on-rails 如何通过关联在has_many中使用回调?

nfg76nw0  于 2023-04-22  发布在  Ruby
关注(0)|答案(4)|浏览(187)

我有一个通过has_many与Project模型关联的Task模型,并且需要在通过关联删除/插入之前操作数据。
由于“自动删除连接模型是直接的,不会触发销毁回调。”我不能为此使用回调。
在任务中,我需要所有project_id来计算任务保存后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
wztqucjr

wztqucjr1#

似乎我必须使用关联回调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
w3nuxt5m

w3nuxt5m2#

我就是这么做的
在模型中:

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

在我的库文件夹中:

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

3pmvbmvn3#

更新连接模型关联,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,这将非常有用。

ssm49v7z

ssm49v7z4#

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

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

应该可以

相关问题