我的替代到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