# Observable mixin # # Adapted from various sources by Brian Amberg # # FIXME: Name sources # Mixin that allows closures to be registered with certain events # # Usage: # class Observed # include Observable # # def foo # signal_event(:foo, 'Foo happened') # end # end # # class Observer # def initialize(observed) # observed.register(:foo) do | o, *args | # puts "Observed object #{o} signalled foo with arguments #{args.inspect}" # end # end # end # # observed = Observed.new # observer = Observer.new(observed) # observed.foo #-- # FIXME: Include optional ID for better deregistration. module Observable # Register an event with the observed class # register(:foo) do | observed, *args | [do something] end def register(event=nil, id=nil, &callback) @observers ||= Hash.new @observers[event] ||= [] @observers[event] << [id, callback] self end # Deregister an event with the observed class # # deregister(:foo, &callback) def deregister(event=nil, id=nil, &callback) @observers ||= Hash.new @observers[event] ||= [] @observers.delete_if { | (a_id, a_callback) | (id && (a_id == id)) || (a_callback == callback) } self end protected # Signal an event to all observers # signal_event(:foo) def signal_event(event = nil, *args) @observers ||= Hash.new @observers[event] ||= [] @observers[event].each do | (id, callback) | callback.call(self, *args) end end end