我有一个方法,只要创建或销毁依赖项,就会更新父类的依赖对象的数量。这通常有效,但出于某种原因,当父类被第三类删除时,使用:dependent => :destroy,当调用count方法时,我得到父对象的nil错误,因此没有任何内容被删除。如果我在此操作期间尝试从count方法提升parent.inspect,则会返回它,因此它显然不是nil。有什么想法吗?
class DependentObject < ActiveRecord::Base
belongs_to :parent
belongs_to :third_object
after_destroy :count
def count
count = DependentObject.count(:all, :conditions => ['parent_id = ?', self.parent_id])
self.parent.count = count
self.parent.save
end
end
class Parent < ActiveRecord::Base
belongs_to :third_object
has_many :dependent_objects, :dependent => :delete_all
end
class ThirdObject
has_many :parents, :dependent => :destroy
has_many :dependent_objects, :dependent => :destroy
end
编辑:我之所以:dependent =&gt;父方法中的delete_all是我天真地假设,因为:delete_all不会触发:after_destroy并且只会在父类被销毁时被调用,它会避免这个问题。查看开发日志,确实是这种情况,因为它在所有相关对象中显示“DependentObject Delete all”,然后再执行“DependentObject Destroy all”并遇到nil错误并启动回滚。
答案 0 :(得分:4)
ActiveRecord喜欢缓存已使用的关联对象。我想这可能就是你的问题所在。
执行third_obj.dependent_objects
时,对象将加载到内存中并进行缓存。然后当你摧毁third_obj
时,它会摧毁parents
然后摧毁dependent_objects
。但是如果有缓存的obj,而不是从db中加载它们来销毁它们,它会在缓存版本上调用destroy,它具有陈旧的父ID,并且已经不再存在于db中。
解决此问题的一种方法是重新排序has_many
声明,以便以其他顺序调用destroys。
has_many :dependent_objects, :dependent => :destroy
has_many :parents, :dependent => :destroy
这会有一些额外的sql调用,但不会有nil问题。 但是有更好的方法来计算事物。 e.g。
parent.dependent_objects.count #does a sql count query--much faster
#than loading all the obj in memory
您还可以在父{q}个:counter_cache => true
声明中使用has_many :dependent_objects
选项,并在父表dependent_objects_count