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> |