Rails has_many使用关联id而不是在destroy上调用callback

时间:2016-10-12 17:06:20

标签: ruby-on-rails

更新after_commit关系并销毁记录时,不会触发has_many回调。

我有一段感情

class Expertise
  has_many :doctor_expertises
  has_many :doctor_profiles, through: :doctor_expertises

class DoctorExpertise
  belongs_to :doctor_profile
  belongs_to :expertise

  after_commit :do_something

  def do_something
     # not called when record destroyed 
  end

在我的控制器中,我使用以下方法更新has_many关系

  def create
    doc = DoctorProfile.find(params[:doctor_id])
    doc.expertise_ids = params[:expertise_ids].select do |x|
      x.to_i > 0
    end
    doc.save!

    render json: doc.expertises
  end

我知道我应该在关系上使用updatedestroy。但是,为什么after_commit在被销毁时不会被记录调用?

我猜这与我设置doc.expertise_ids不触发回调的方式有关。但是,除了简要here之外,我无法找到有关此方法的任何文档。是否有文件证实或否认这种怀疑或是否还有其他事情发生?

3 个答案:

答案 0 :(得分:1)

来自您关联的RailsGuides:

自动删除联接模型是直接的,不会触发销毁回调。

虽然它没有说明after_commit,但它很可能也不会被解雇

我认为您正在寻找的答案就在这里:

Howto use callbacks in a has_many through association?

您需要在has_many声明中使用after_remove

答案 1 :(得分:0)

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

解决方案1 ​​

添加或删除关联时调用某些回调的一种方法是使用Association Callbacks

class Expertise
  has_many :doctor_expertises
  has_many :doctor_profiles, through: :doctor_expertises
           before_remove: :my_before_remove,
           after_remove: my_after_remove           

  def my_before_remove(doctor_profile)
    ...
  end

  def my_after_remove(doctor_profile)
    ...
  end
end

解决方案2

在删除记录时,Force Rails调用destroy而不是delete。 为此,请安装gem replace_with_destroy并将选项replace_with_destroy: true传递给 has_many 关联。

class Expertise
  has_many :doctor_expertises
  has_many :doctor_profiles, through: :doctor_expertises,
            replace_with_destroy: true        
  ...
end

class DoctorExpertise
  belongs_to :doctor_profile
  belongs_to :expertise

  after_commit :do_something

  def do_something
     # this will be called when updating Expertise.doctor_profiles
     # because use destroyed instead delete to remove the record
  end

这样,您可以确保Rails调用所有destroy callbacks

答案 2 :(得分:0)

像这样添加dependent: :destroy

has_many :doctor_profiles, through: :doctor_expertises, dependent: :destroy

我知道对 has_many 进行依赖销毁有点误导,但它会触发销毁回调并且不会销毁基本记录,只会销毁连接记录。参考:https://github.com/collectiveidea/audited/issues/246