2013-01-15 18 views
4

我有一種情況,我想在另一個對象被銷燬後更新父對象的依賴關係。下面是類層次結構的一個例子: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中的保存,但這似乎也不起作用。

任何幫助將不勝感激,謝謝!

回答

7

我看到有被2種選擇:

  1. 不要使用條件一after_destroy回調,而是期望信息由不管是誰破壞的條件進行重新計算。這是最乾淨的,因爲你解耦了兩個單獨的意圖:對象破壞和計算。如果某天你想一次銷燬兩個條件並在兩個條件都被銷燬後才重新計算,你可以看到這會更有幫助。你不能用回調來做到這一點。它也與Law of Demeter更接近 - 調用者Condition.destroy調用info.recalculate比條件調用parent.info.recalculate要好。

    如果您確實想在「條件」中打包此行爲,請使用隱藏式回調類型創建一個名爲#destroy_and_recalculate的函數,而不是僅調用#destroy。來電者更明顯的是你將啓動重新計算。

  2. 父的:condition協會刪除:dependent=>destroy,並用自己的before_destroy回調上Parent這將導致condition在沒有回調被破壞更換。

    在條件下,我會創建此方法,例如#destroy_without_callbacks,並在其中destroy條件的孩子,然後導致條件delete本身。

:dependent=>destroy功能是偉大的,但像這樣的循環,我認爲迄今最清晰的方法是使它非常明確自己在做什麼的帶走了一些魔術和管理對象,流程生命週期更加明確。

相關問題