我的替代到Rails 3個觀察員是一個手工執行,它利用模型中定義的回調還設法(如agmin上面他的回答狀態)「翻轉的依賴......耦合」。
我的對象從基類,其提供了用於註冊觀察員繼承:
class Party411BaseModel
self.abstract_class = true
class_attribute :observers
def self.add_observer(observer)
observers << observer
logger.debug("Observer #{observer.name} added to #{self.name}")
end
def notify_observers(obj, event_name, *args)
observers && observers.each do |observer|
if observer.respond_to?(event_name)
begin
observer.public_send(event_name, obj, *args)
rescue Exception => e
logger.error("Error notifying observer #{observer.name}")
logger.error e.message
logger.error e.backtrace.join("\n")
end
end
end
end
(當然,在超過繼承組合物的精神,上述代碼可以被放置在模塊中並混合在每個模型中。 )
一個初始化寄存器觀察員:
User.add_observer(NotificationSender)
User.add_observer(ProfilePictureCreator)
每個模型就可以定義自己觀察到的事件,超出了基本的ActiveRecord callba中正。例如,我的用戶模型公開2個事件:
class User < Party411BaseModel
self.observers ||= []
after_commit :notify_observers, :on => :create
def signed_up_via_lunchwalla
self.account_source == ACCOUNT_SOURCES['LunchWalla']
end
def notify_observers
notify_observers(self, :new_user_created)
notify_observers(self, :new_lunchwalla_user_created) if self.signed_up_via_lunchwalla
end
end
一個希望收到通知,僅僅需要(1)與公開的事件和(2)有他的名字的方法模型註冊這些事件的任何觀察員匹配事件。正如人們所預料的,多個觀察者可以爲同一個事件註冊,並(在參考了原來的問題的第2段),觀察員可以觀看跨越幾個型號的事件。下面
的NotificationSender和ProfilePictureCreator觀察者類定義方法不同模式暴露的事件:
NotificationSender
def new_user_created(user_id)
...
end
def new_invitation_created(invitation_id)
...
end
def new_event_created(event_id)
...
end
end
class ProfilePictureCreator
def new_lunchwalla_user_created(user_id)
...
end
def new_twitter_user_created(user_id)
...
end
end
一個需要注意的是,在所有模型中公開的所有事件的名稱必須是唯一的。
我真的很驚訝有沒有張貼這個問題更多的答案。有點令人不安。 – courtsimas 2013-05-07 20:05:21
https://github.com/krisleech/wisper – Kris 2013-05-17 14:36:26