删除孤儿父母

我有这样的关系:

Parent has_many :children Child belongs_to :parent 

我想要做的是删除父母,如果没有更多的孩子。 所以要做到这一点,我有:

 Child before_destroy :destroy_orphaned_parent def destroy_orphaned_parent parent.children.each do |c| return if c != self end parent.destroy end 

这工作正常,但我想将父级的删除级联到子级。 我通常会这样做:

 Parent has_many :children, :dependent => :destroy 

这会导致WebRick服务器在测试时崩溃。 我假设这是由于最后一个孩子的无限循环删除父母删除孩子等。

我开始认为有更好的方法来做到这一点? 有人有主意吗? 有没有办法防止这种递归?

一些想法:

  • 您可以删除after_destroy孤立父after_destroy (使用http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/a3f12d578f5a2619上的语句查找它们)

  • 您可以在包含父ID的before_destroy中设置一些实例变量,然后在after_destroy回调中根据此id进行查找,并根据after_destroy计数来决定是否删除父项

我通过以下方式完成了这项工作:

  before_destroy :find_parent after_destroy :destroy_orphaned_parent def find_parent @parent = self.parent end def destroy_orphaned_parent if @parent.children.length == 0 @parent.destroy end end 

根据Anwar的建议,这也可以使用around回调来完成,如下所示:

  around_destroy :destroy_orphaned_parent def destroy_orphaned_parent parent = self.parent yield # executes a DELETE database statement if parent.children.length == 0 parent.destroy end end 

我没有测试过上述解决方案,如有必要,请随时更新。

使用after_destroy回调。

 after_destroy :release_parent def release_parent if parent.children.count.zero? parent.destroy end end 

使用Rails 3.2.15

您可以使用around_destroy回调来完成此操作

 around_destroy :destroy_orphaned_parent def destroy_orphaned_parent @parent = self.parent yield @parent.destroy if @parent.children.length == 0 end 
 after_destroy :destroy_parent, if: parent_is_orphan? private def parent_is_orphan? parent.children.count.zero? end def destroy_parent parent.destroy end