Callbacks Implementation in Ruby
Callbacks are helpful when you don’t want to combine different objects without a need to hardcode references to each other. Ruby’s callback system allows objects to register code blocks. In this case, the objects can issue a call out to registered callbacks or send notifications to callback as per needed bases.
Ruby’s way of implementing callbacks requires to write register or subscribe methods for accepting code blocks. Secondly, we need to store code blocks as Proc objects in an array or hash. Arrays are used to store one type of callback and hashes are used to store multi-type callbacks. Finally, in order to call a registered callback, you need to iterate over these two types of data structures.
This technique has many names such as callbacks, hook methods, plugins, subscribe and publish. In its core they are all the same. They are all designed to have an object to ask another object to call a piece of code (callback) then certain condition meets.
module EventDispatch
def setup_listeners
@event_dispatcher = {}
end
def subscribe(event, &callback)
(@event_dispatcher[event] ||=[])<<callback
end
protected
def notify(event, *args)
if @event_dispatcher[event]
@event_dispatcher[event].each do |message|
message.call(*args) if message.respond_to? :call
end
end
return nil
end
end
class Factory
include EventDispatch
def initialize
setup_listeners
end
def make_widget(color)
notify(:new_widget, color)
end
end
class WidgetListener
def initialize(factory)
@count = Hash.new(0)
factory.subscribe(:new_widget) do |color|
@count[color]+=1
puts “#{@count[color]} colors of #{color} type”
end
end
end
We need to issue several call in order to see it in action.
factory1 = Factory.new
WidgetListener.new(factory1)
factory1.make_widget(“blue”) //1 colors of blue type
factory1.make_widget(“red”) //1 colors of red type