J
James Coglan
[Note: parts of this message were removed to make it a legal post.]
eventful version 1.0.0 has been released!
* <http://github.com/jcoglan/eventful>
+Eventful+ is a small extension on top of Ruby's +Observable+ module that
implements named events, block listeners and event bubbling. It allows
much more flexible event handling behaviour than is typically allowed
by +Observable+, which requires listeners to be objects that implement
+update+ and provides no simple way of calling subsets of observers based
on event type.
== Examples
Make a class listenable by mixing +Eventful+ into it:
class Watcher
include Eventful
end
Register event listeners using +on+ with an event name and a block.
Publish events using +fire+ with the event name. The block accepts
the object that published the event, along with any parameters passed
to +fire+.
w = Watcher.new
w.onfilechange) { |watcher, path| puts path }
w.onfiledelete) { |watcher, path| puts "#{ watcher } deleted #{ path }"
}
w.firefilechange, '/path/to/file.txt')
w.firefiledelete, '/tmp/pids/event.pid')
# prints...
# /path/to/file.txt
# #<Watcher:0xb7b485a4> deleted /tmp/pids/event.pid
The +on+ method returns the +Observer+ object used to represent the
listener,
so you can remove it using +delete_observer+.
obs = w.onfilechange) { |watcher| ... }
# listener will not fire after this
w.delete_observer(obs)
=== Method chains instead of blocks
Instead of passing a block, you can add behaviour to objects by chaining
method calls after the +on+ call. For example:
class Logger
include Eventful
def print(message)
puts message
end
end
log = Logger.new
log.onreceive).print "Received message"
# Calls `log.print "Received message"`
log.firereceive)
=== Events that bubble
When you +fire+ an event, the event 'bubbles' up the type system. What
this means is that you can listen to events on all the instances of a
class just by placing an event listener on the class itself. As above,
the listener is called with the instance that fired the event.
Logger.onreceive) { |log, msg| puts "#{ log } :: #{ msg }" }
l1, l2 = Logger.new, Logger.new
l1.firereceive, 'The first message')
l2.firereceive, 'Another event')
# prints...
# #<Logger:0xb7bf103c> :: The first message
# #<Logger:0xb7bf1028> :: Another event
Method chains can also be used, and they will be replayed on the instance
that initiated the event.
# Calls `log.print "Received message"`
Logger.onreceive).print "Received message"
log = Logger.new
log.firereceive)
eventful version 1.0.0 has been released!
* <http://github.com/jcoglan/eventful>
+Eventful+ is a small extension on top of Ruby's +Observable+ module that
implements named events, block listeners and event bubbling. It allows
much more flexible event handling behaviour than is typically allowed
by +Observable+, which requires listeners to be objects that implement
+update+ and provides no simple way of calling subsets of observers based
on event type.
== Examples
Make a class listenable by mixing +Eventful+ into it:
class Watcher
include Eventful
end
Register event listeners using +on+ with an event name and a block.
Publish events using +fire+ with the event name. The block accepts
the object that published the event, along with any parameters passed
to +fire+.
w = Watcher.new
w.onfilechange) { |watcher, path| puts path }
w.onfiledelete) { |watcher, path| puts "#{ watcher } deleted #{ path }"
}
w.firefilechange, '/path/to/file.txt')
w.firefiledelete, '/tmp/pids/event.pid')
# prints...
# /path/to/file.txt
# #<Watcher:0xb7b485a4> deleted /tmp/pids/event.pid
The +on+ method returns the +Observer+ object used to represent the
listener,
so you can remove it using +delete_observer+.
obs = w.onfilechange) { |watcher| ... }
# listener will not fire after this
w.delete_observer(obs)
=== Method chains instead of blocks
Instead of passing a block, you can add behaviour to objects by chaining
method calls after the +on+ call. For example:
class Logger
include Eventful
def print(message)
puts message
end
end
log = Logger.new
log.onreceive).print "Received message"
# Calls `log.print "Received message"`
log.firereceive)
=== Events that bubble
When you +fire+ an event, the event 'bubbles' up the type system. What
this means is that you can listen to events on all the instances of a
class just by placing an event listener on the class itself. As above,
the listener is called with the instance that fired the event.
Logger.onreceive) { |log, msg| puts "#{ log } :: #{ msg }" }
l1, l2 = Logger.new, Logger.new
l1.firereceive, 'The first message')
l2.firereceive, 'Another event')
# prints...
# #<Logger:0xb7bf103c> :: The first message
# #<Logger:0xb7bf1028> :: Another event
Method chains can also be used, and they will be replayed on the instance
that initiated the event.
# Calls `log.print "Received message"`
Logger.onreceive).print "Received message"
log = Logger.new
log.firereceive)