12

dependent: :destroy以循环问题为例:

class User < ActiveRecord::Base
  has_one: :staff, dependent: :destroy
end

class Staff < ActiveRecord::Base
  belongs_to :user, dependent: :destroy
end

如果我打电话user.destroy,关联的staff也应该被销毁。相反,调用staff.destroy也应该破坏关联user

这在 Rails 3.x 中效果很好,但是在 Rails 4.0(并在 4.1 中继续)中行为发生了变化,因此形成了一个循环,最终你会得到一个错误,“堆栈级别太深”。before_destroy一种明显的解决方法是使用或after_destroy手动销毁关联对象而不是使用该dependent: :destroy机制来创建自定义回调。甚至GitHub 中针对这种情况打开的问题也有几个人推荐了这种解决方法。

不幸的是,我什至无法让这种解决方法发挥作用。这就是我所拥有的:

class User < ActiveRecord::Base
  has_one: :staff

  after_destroy :destroy_staff

  def destroy_staff
    staff.destroy if staff and !staff.destroyed?
  end
end

这不起作用的原因是它staff.destroyed?总是返回false。于是就形成了一个循环。

4

2 回答 2

5

如果循环的一侧只有一个回调,您可以将其中一个替换dependent: :destroydependent: :delete

class User < ActiveRecord::Base
  # delete prevents Staff's :destroy callback from happening
  has_one: :staff, dependent: :delete
  has_many :other_things, dependent: :destroy
end

class Staff < ActiveRecord::Base
  # use :destroy here so that other_things are properly removed
  belongs_to :user, dependent: :destroy
end

对我来说效果很好,只要一侧不需要其他回调即可触发。

于 2014-11-24T06:09:12.960 回答
4

我也遇到了这个问题,并提出了一个不漂亮但有效的解决方案。本质上,您只需使用destroy_user类似于destroy_staff.

class User < ActiveRecord::Base
  has_one: :staff

  after_destroy :destroy_staff

  def destroy_staff
    staff.destroy if staff && !staff.destroyed?
  end
end

class Staff < ActiveRecord::Base
  belongs_to :user

  after_destroy :destroy_user

  def destroy_user
    user.destroy if user && !user.destroyed?
  end
end
于 2014-05-22T06:09:05.827 回答