是否存在Rails 4循环依赖::破坏变通方法?

作为循环dependent: :destroy的示例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_destroyafter_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 。 所以它形成了一个循环。

如果循环的一侧只有一个回调,则可以替换其中一个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 

只要一方不需要其他回调就可以为我工作。

我也遇到了这个问题,并提出了一个不太漂亮但有效的解决方案。 基本上,您只需使用与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