Skip to content

Instantly share code, notes, and snippets.

@swerling
Last active December 23, 2015 22:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swerling/6705931 to your computer and use it in GitHub Desktop.
Save swerling/6705931 to your computer and use it in GitHub Desktop.
Ruby Observable uses idiom similar to smalltalk circa 1980. This gist creates MotoObservable with style similar to smalltalk circa 1999.
# Example program at the bottom. This gist can be copy/pasted into a file and run
#================= MotoObservable
require 'set'
# 1. Subscribe using 'when, send, to' terminology to register any method on any object as an event callback
# 2. Use 'trigger_event' to trigger an event along with arbitrary number of arguments
# 3. Simple way of unregistering
module MotoObservable
def _handlers
@_handlers ||= {}
end
def when(opts={})
if opts[:send].nil?
(self._handlers[opts[:event]] ||= {}).delete(opts[:to])
else
(self._handlers[opts[:event]] ||= {})[opts[:to]] = opts[:send]
end
end
def trigger_event evt, *args
self._handlers[evt].each do |observer, callback|
observer.send(callback, *args)
end
end
end
#================= Example Program
# first the tv
class TV
include MotoObservable
end
# Now the tv
class CouchPotato
def wake_up_and_repeat_line_from_tv(message, time)
sleep Kernel.rand(2.0) # (waking up)
puts "CouchPotato says: 'Hey, the TV said \"#{message}\" at #{time}"
end
end
tv = TV.new
potato = CouchPotato.new
tv.when(event: :dialog, send: :wake_up_and_repeat_line_from_tv, to: potato)
tv.trigger_event(:dialog, Time.now, "Real housewives from OC up next") #=> CouchPotato says:...
tv.when(event: :dialog, send: nil, to: potato) # Unregister
tv.trigger_event(:dialog, Time.now, "Real housewives from OC up next") #=> nothing happens since we unregistered
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment