Skip to content

Instantly share code, notes, and snippets.

@snipsnipsnip
Last active December 21, 2015 06:09
Show Gist options
  • Save snipsnipsnip/6262047 to your computer and use it in GitHub Desktop.
Save snipsnipsnip/6262047 to your computer and use it in GitHub Desktop.
news.rb
require 'weakref'
# ニュース。グローバルpubsub。
#
# News.newsで発信。こんなふうに書く。
#
# 誰かの誕生日があったことを発信する。
#
# def tick
# News.news(:birthday) if @month == 10 && @day == 5
# end
#
# 誰の誕生日なのか一緒に伝えることもできる。
# news(:birthday, "masao")
#
# オプションはいくつでも指定できる。
# news(:birthday, "masao", 30)
#
# News.listenで受信。initializeでこんなふうに書く。
#
# class Fairy
# include News
#
# def initialize
# listen :birthday do |who, age|
# # 誰かが誕生日を迎えたらここが実行される
# print "happy birthday #{who}!"
# if age == 30
# print "I have a present for you..."
# end
# end
# end
# end
module News
Listeners = {}
# 指定した名前のニュースを購読する。
# ブロックから :mute を返すと購読をやめる。
# listen(:ニュース名) { イベント時ここが実行される }
def listen(name, &blk)
puts "#{caller[0]}: listen #{name}" if $DEBUG
(Listeners[name] ||= []) << [WeakRef.new(self), blk]
end
module_function
# 購読者全員を呼び出して回る。
def news(name, *info)
puts "#{caller[0]}: report #{name} (#{info.inspect})" if $DEBUG
if listeners = Listeners[name]
listeners.reject! do |listener, callback|
!listener.weakref_alive? || :mute == callback.call(*info)
end
end
end
# 購読者を全員忘れる。
def self.clear_listener
Listeners.clear
nil
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment