This page contains automated test results for code from O'Reilly's Ruby Cookbook. If this code looks interesting or useful, you might want to buy the whole book.
| Coupling Systems Loosely with Callbacks | ||
|---|---|---|
| Code | Expected | Actual |
module EventDispatcher
def setup_listeners
@EventDispatcher_listeners = {}
end
def subscribe(event, &callback)
(@EventDispatcher_listeners[event] ||= []) << callback
end
protected
def notify(event, *args)
if @EventDispatcher_listeners[event]
@EventDispatcher_listeners[event].each do |m|
m.call(*args) if m.respond_to? :call
end
end
return nil
end
end
class Factory
include EventDispatcher
def initialize
setup_listeners
end
def produce_widget(color)
#Widget creation code goes here...
notify(:new_widget, color)
end
end
class WidgetCounter
def initialize(factory)
@counts = Hash.new(0)
factory.subscribe(:new_widget) do |color|
@counts[color] += 1
puts "#{@counts[color]} #{color} widget(s) created since I started watching."
end
end
end
f1 = Factory.new
WidgetCounter.new(f1)
f1.produce_widget("red") |
1 red widget(s) created since I started watching. |
1 red widget(s) created since I started watching. |
f1.produce_widget("green") |
1 green widget(s) created since I started watching. |
1 green widget(s) created since I started watching. |
f1.produce_widget("red") |
2 red widget(s) created since I started watching. This won't produce any output, since our listener is listening to another Factory. |
2 red widget(s) created since I started watching. |
Factory.new.produce_widget("blue")
module EventDispatcher
def notify(event, *args)
if @EventDispatcher_listeners[event]
@EventDispatcher_listeners[event].each do |m|
yield(m.call(*args)) if m.respond_to? :call
end
end
return nil
end
end
class Portal
include EventDispatcher
def initialize
setup_listeners
end
def render
puts '<table>'
render_block = Proc.new { |box| puts " <td>#{box}</td>" }
[:row1, :row2].each do |row|
puts ' <tr>'
notify(row, &render_block)
puts ' </tr>'
end
puts '</table>'
end
end
portal = Portal.new
portal.subscribe(:row1) { 'Stock Ticker' }
portal.subscribe(:row1) { 'Weather' }
portal.subscribe(:row2) { 'Pointless, Trivial News' }
portal.render |
<table> <tr> <td>Stock Ticker</td> <td>Weather</td> </tr> <tr> <td>Pointless, Trivial News</td> </tr> </table> |
<table> <tr> <td>Stock Ticker</td> <td>Weather</td> </tr> <tr> <td>Pointless, Trivial News</td> </tr> </table> |