今日の@avdiのRubyTapasエピソードから次のコードを取得しました。
module Eventful
def self.included(other)
other.extend(Macros)
end
def add_listener(listener)
(@listeners ||= []) << listener
end
def notify_listeners(event, *args)
(@listeners || []).each do |listener|
listener.public_send("on_#{event}", *args)
end
end
module Macros
def event(name)
module_eval(%Q{
def #{name}(*args)
notify_listeners(:#{name}, *args)
end
})
end
end
end
class Dradis
include Eventful
event :new_contact
end
class ConsoleListener
def on_new_contact(direction, range)
puts "DRADIS contact! #{range} kilometers, bearing #{direction}"
end
end
dradis = Dradis.new
dradis.add_listener(ConsoleListener.new)
dradis.new_contact(120, 23000)
イベントとリスナーの概念とオブザーバーパターンは理解していますが、この構文がどのように/なぜ機能するのか理解できず、どのマニュアルにも見られません。クラスDradis
にはこれがあります:
event :new_contact
最初は、それevent
はメソッドであり、次のようなインスタンスを:new_contact
呼び出すための引数だと思いました。event
Dradis
dradis = Dradis.new
dradis.event
しかし、代わりに、次のようなnew_contact
インスタンスで呼び出されます。Dradis
dradis = Dradis.new
dradis.add_listener(ConsoleListener.new)
dradis.new_contact(120, 23000)
event
これにより、マクロモジュールのメソッドがトリガーされます。
なぜそれがこのように機能するのか誰かが説明できますか?イベントメソッドをトリガーする:new_contact
ためにインスタンスを呼び出しますか?dradis