ものすごい必要だったので作った。


rubygemsに登録しておいたので

gem install event_emitter
で使える。

ドキュメントはここ
Ruby EventEmitter

バグ、機能要望などは
githubのissuetwitterかメールでお願いします


EventEmitterとは


Node.jsのコアライブラリ。lib/events.jsにある。
nvmでnodeをインストールすると ~/.nvm/src/node-v0.8.14/lib/events.js とかにある。

どんなオブジェクトにでも一発でonとemitという関数を追加できて、
obj.on(‘イベント名’, コールバック)でコールバック登録して
obj.emit(‘イベント名’, 引数)でイベントを発火させる。

nodeの全てのライブラリがイベント駆動するためによく使ってる機能。
addEventListenerとかよりも使いやすい。


ruby実装


onとemitをクラス宣言時にmix-inしたり、既存のクラスや特定のインスタンスに後から追加したりできる。

require "rubygems"
require "event_emitter"

class User
include EventEmitter ## mix-in
attr_accessor :name
end

user = User.new
user.name = "shokai"
user.on :go do |data|
puts "#{name} #{data[:place]}に行く"
end

user.emit :go, {:place => "かずすけ"}
# => "shokai かずすけに行く"
userインスタンスに登録したイベントはuserインスタンスの中で実行されるので、”name”だけでuser.nameの中身の”shokai”が参照できている。



onのかわりにonceで登録すると、一度だけ実行されるイベントを登録できる。
user.once :eat do |data|
puts "#{name} -> #{data}"
end

user.emit :eat, "BEEF" # => "shokai -> BEEF"
user.emit :eat, "Ramen" # => 実行されない


ごく普通のインスタンスにEventEmitter.applyすると、on/emitが追加される。特異メソッド。
EventEmitter.apply インスタンス名


既存のクラスにapplyするとクラスが拡張される
EventEmitter.apply クラス名


イベント駆動じゃないクラスとかも強引にイベント駆動にできそうですね。


参考にした


JSだと全部オブジェクトなのでシンプルなんだけど、Rubyのクラスやインスタンスやら全部にon/emit追加できるようにするのちょっと理解が大変だった。
このへんの黒魔術を参考にした。