ruby-on-rails – after_destroy子回调可以保存父项的依赖关系,在父项被销毁时会导致问题

我有一种情况,我希望在另一个对象被销毁后更新父对象的依赖项.以下是类层次结构的示例:

class Parent < ActiveRecord::Base
  has_one  :info,:dependent => :destroy
  has_many :conditions,:dependent => :destroy
  ....
end

class Info < ActiveRecord::Base
  belongs_to :parent

  def recalculate
    # Do stuff
  end
  ....
end

class Condition < ActiveRecord::Base
  belongs_to :parent
  has_one :condition_detail

  after_destroy :update_info

  def update_info
    parent.info.recalculate
    parent.info.save(:validate => false)
  end
  ....
end

问题是当父节点被销毁时,它会销毁这个条件,然后它会引发after_destroy回调并在信息对象被销毁后保存它.所以在父母被破坏后,信息仍然存在.如果我没有绕过验证,保存将无声地失败,这是我不想要的.并使用保存!提出异常.

Condition上的回调必须是after_destroy,否则Info上的重新计算方法将无法正确表示关系状态以计算它需要的内容.

我觉得当父母被摧毁时我需要一种绕过回调的方法,但我不认为这是可能的.我不能使用dependent => delete_all因为它不会破坏Condition的子节点.我试过看看是否有一种方法可以判断父母是否已经对其进行了销毁并使用该信息来绕过after_destroy中的保存,但这似乎也没有用.

任何帮助将不胜感激,谢谢!

解决方法

我看到有两种选择:

>不要在Condition上使用after_destroy回调,而是期望任何正在销毁Condition的人重新计算信息.这是最干净的,因为你将两个独立的意图分离:对象破坏和计算.如果有一天你想要一次破坏2个条件并且只有在两个条件被销毁之后才重新计算,你可以看到这会更有用.你不能通过回调来做到这一点.它还与Law of Demeter更紧密地对齐 – Condition.destroy的调用调用info.recalculate比调用parent.info.recalculate的Condition更好.

如果您真的想要在Condition中打包此行为,请创建一个调用的#destroy_and_recalculate函数,而不仅仅是带有隐藏式回调的#destroy.对于呼叫者来说,您将开始重新计算更为明显.
>删除:dependent =>销毁父级的:条件关联,并将其替换为您自己的Parent上的before_destroy回调,这将导致条件在没有回调的情况下被销毁.

在Condition中,我会创建这个方法,例如#destroy_without_callbacks,并在其中销毁Condition的子节点,然后导致条件删除自身.

功能:dependent => destroy很棒,但是对于像这样的循环,我认为迄今为止最清晰的方法是通过消除一些魔法并管理对象和进程生命周期来使其非常清晰.更明确地说.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...