2009-07-02 44 views
1

我有一種方法,在創建或銷燬依賴項時更新父類的依賴對象的計數。這通常起作用,但由於某種原因,當父類被第三個類用:dependent =>:destroy刪除時,當count方法被調用時,父類對象會得到一個零錯誤,因此不會被刪除。如果我在這個操作過程中嘗試從count方法提升parent.inspect,它會返回,所以顯然不是零。有什麼想法嗎?after_destroy上的無對象

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 

編輯:我之所以有:依賴=>父方法DELETE_ALL是我天真地認爲,因爲:DELETE_ALL不觸發:after_destroy當父母被銷燬,只會被調用,它會避免這個問題。查看開發日誌,事實上就是這樣的,因爲它在之前通過'DependentObject Destroy all'並遇到nil錯誤並啓動回滾之前會對所有相關對象表示'DependentObject Delete all'。

回答

4

ActiveRecord喜歡緩存使用的關聯對象。我認爲這可能是你的問題所在。 當你做third_obj.dependent_objects對象被加載到內存並被緩存。那麼當你銷燬third_obj時,它會銷燬parents,然後銷燬dependent_objects。但是,如果存在緩存的obj,而不是從數據庫中加載它們以銷燬它們,則會調用緩存的版本,該緩存的版本具有陳舊的父ID,並且已不再存在於數據庫中。

解決此問題的一種方法是對has_many聲明進行重新排序,以便以其他順序調用破壞。

has_many :dependent_objects, :dependent => :destroy 
    has_many :parents, :dependent => :destroy 

這將有一些額外的SQL調用,但不會有零問題。 但有更好的方法來計算的東西。例如

parent.dependent_objects.count #does a sql count query--much faster 
           #than loading all the obj in memory 

,你也可以使用在父母的has_many :dependent_objects聲明:counter_cache => true選項和列添加到父母表dependent_objects_count

+0

這是絕對理想。非常感謝! – Optimate 2009-07-02 20:23:00