at.*_*at. 12 ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 ruby-on-rails-4.1
作为循环dependent: :destroy问题的一个例子:
class User < ActiveRecord::Base
has_one: :staff, dependent: :destroy
end
class Staff < ActiveRecord::Base
belongs_to :user, dependent: :destroy
end
Run Code Online (Sandbox Code Playgroud)
如果我打电话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
Run Code Online (Sandbox Code Playgroud)
这不起作用的原因是staff.destroyed?始终返回false.所以它形成了一个循环.
如果循环的一侧仅具有一个回调,可以代替的一个dependent: :destroy与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
Run Code Online (Sandbox Code Playgroud)
对我来说很有用,只要一方不需要其他回调来解雇.
我也遇到了这个问题,并提出了一个不太漂亮但有效的解决方案。本质上,您只需使用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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1746 次 |
| 最近记录: |