是否有 Rails 4 循环依赖::destroy 解决方法? [英] Is there a Rails 4 circular dependent: :destroy workaround?
问题描述
以循环dependent: :destroy
问题为例:
class User
如果我调用 user.destroy
,关联的 staff
也应该被销毁.相反,调用 staff.destroy
也应该销毁关联的 user
.
这在 Rails 3.x 中效果很好,但在 Rails 4.0 中行为发生了变化(并在 4.1 中继续),从而形成循环并最终出现错误,堆栈级别太深".一种明显的解决方法是使用 before_destroy
或 after_destroy
创建自定义回调来手动销毁关联的对象,而不是使用 dependent::destroy
机制.甚至 GitHub 中为此打开的问题 也有一些人推荐这种解决方法.>
不幸的是,我什至无法使该解决方法起作用.这就是我所拥有的:
class User
这不起作用的原因是 staff.destroyed?
总是返回 false
.所以就形成了一个循环.
如果循环的一侧只有那个回调,你可以用 替换
dependent::destroy
之一依赖: :delete
class User
对我来说效果很好,只要一侧不需要其他回调即可触发.
As an example for the circular dependent: :destroy
issue:
class User < ActiveRecord::Base
has_one: :staff, dependent: :destroy
end
class Staff < ActiveRecord::Base
belongs_to :user, dependent: :destroy
end
If I call user.destroy
, the associated staff
should be destroyed as well. Conversely, calling staff.destroy
should destroy the associated user
as well.
This worked great in Rails 3.x, but the behavior changed in Rails 4.0 (and continues in 4.1) such that a loop forms and eventually you get an error, "stack level too deep." One obvious workaround is to create a custom callback using before_destroy
or after_destroy
to manually destroy the associated objects instead of using the dependent: :destroy
mechanism. Even the issue in GitHub opened for this situation had a couple people recommending this workaround.
Unfortunately, I can't even get that workaround to work. This is what I have:
class User < ActiveRecord::Base
has_one: :staff
after_destroy :destroy_staff
def destroy_staff
staff.destroy if staff and !staff.destroyed?
end
end
The reason this doesn't work is that staff.destroyed?
always returns false
. So it forms a cycle.
If one side of the cycle only has that one callback, you can replace one of the dependent: :destroy
with dependent: :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
Worked great for me, as long as one side doesn't need other callbacks to fire.
这篇关于是否有 Rails 4 循环依赖::destroy 解决方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!