2009-10-07 101 views
32

我想過使用觀察者或回調。 什麼時候應該使用觀察者?觀察者與回調

F.e.你可以做到以下幾點:

# User-model 
class User << AR 
    after_create :send_greeting! 

    def send_greeting! 
    UserNotifier.deliver_greeting_message(self) 
    end 

end 

#observer 
class UserNotifier << AR 
    def greeting_message(user) 
    ... 
    end 
end 

,或者你可以創建一個觀察者,並讓用戶時變得創建它看...

什麼豆你recommened?

回答

9

回調更短暫:您將其傳遞給函數以調用一次。它是API的一部分,你通常不能在不傳遞迴調的情況下調用該函數。這個概念與功能緊密結合。通常,您只能傳遞一個回調函數。

示例:運行線程並給出線程終止時調用的回調函數。

觀察者的壽命較長,可以隨時附加/拆離。可以有許多觀察員爲同一件事情,他們可以有不同的生命週期。

示例:顯示UI中模型的值並從用戶輸入更新模型。

27

您可以使用觀察員作爲解耦或分配責任的手段。從基本意義上說 - 如果你的模型代碼變得太雜亂,就開始考慮使用觀察者來處理一些不必要的行爲。觀察者的真正能力(至少在我看來)是他們作爲你的模型和一些其他子系統的連接點的能力,這些子系統的功能被所有(或某些)其他類使用。假設您決定爲您的應用程序添加即時消息通知 - 例如您想要通知您系統中某些(或全部)模型的一些(或全部)CRUD操作。在這種情況下,使用觀察者將是理想的 - 您的通知子系統將與您的業務邏輯保持完全分離,並且您的模型不會受到與其業務無關的行爲的混亂。觀察員的另一個好用例是審計子系統。

41

與米諾諾塔的答案有關的一個非常重要的區別是,ActiveRecord上的回調函數有能力取消被調用的操作以及所有後續的回調,而觀察者不會這麼做。

class Model < ActiveRecord::Base 
    before_update :disallow_bob 

    def disallow_bob 
    return false if model.name == "bob" 
    end 
end 

class ModelObserver < ActiveRecord::Observer 
    def before_update(model) 
    return false if model.name == "mary" 
    end 
end 

m = Model.create(:name => "whatever") 

m.update_attributes(:name => "bob") 
=> false -- name will still be "whatever" in database 

m.update_attributes(:name => "mary") 
=> true -- name will be "mary" in database 

觀察員只能觀察,他們可能不會介入。

+19

這不再是在rails 3.1中的情況,觀察者可以通過從before_ *返回false來取消保存的操作,這將取消操作,並且可能會在after_ *中引發異常以異常取消操作。 –

+0

謝謝jrizza,我有一個類似的情況,其中一個觀察員失敗導致記錄不存儲,我認爲這是一個不良結果。 –

+2

是的,這很奇怪,它們不再是觀察者,觀察者中的異常會導致提交失敗,並且用戶會得到異常屏幕。對我來說沒有意義。 – Amala