是否有 Rails 4 循环依赖::destroy 解决方法? [英] Is there a Rails 4 circular dependent: :destroy workaround?

查看:45
本文介绍了是否有 Rails 4 循环依赖::destroy 解决方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

class User 

如果我调用 user.destroy,关联的 staff 也应该被销毁.相反,调用 staff.destroy 也应该销毁关联的 user.

这在 Rails 3.x 中效果很好,但在 Rails 4.0 中行为发生了变化(并在 4.1 中继续),从而形成循环并最终出现错误,堆栈级别太深".一种明显的解决方法是使用 before_destroyafter_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆