Permalink
Browse files

implements AS::Notifications.subscribed, which provides subscriptions…

… to events while a block runs
  • Loading branch information...
1 parent b33232f commit d287e90870a9832c9d7e9d222881d3a6102bd04d @fxn fxn committed Nov 5, 2011
View
2 activesupport/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 3.2.0 (unreleased) ##
+* ActiveSupport::Notifications.subscribed provides subscriptions to events while a block runs. *fxn*
+
* Module#qualified_const_(defined?|get|set) are analogous to the corresponding methods
in the standard API, but accept qualified constant names. *fxn*
View
41 activesupport/lib/active_support/notifications.rb
@@ -63,6 +63,40 @@ module ActiveSupport
# and even pass no argument to +subscribe+, in which case you are subscribing
# to all events.
#
+ # == Temporary Subscriptions
+ #
+ # Sometimes you do not want to subscribe to an event for the entire life of
+ # the application. There are two ways two unsubscribe.
+ #
+ # === Subscribe While a Block Runs
+ #
+ # You can subscribe to some event temporarily while some block runs. For
+ # example, in
+ #
+ # callback = lambda {|*args| ... }
+ # ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
+ # ...
+ # end
+ #
+ # the callback will be called for all "sql.active_record" events instrumented
+ # during the execution of the block. The callback is unsubscribed automatically
+ # after that.
+ #
+ # === Manual Unsubscription
+ #
+ # The +subscribe+ method returns a subscriber object:
+ #
+ # subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
+ # ...
+ # end
+ #
+ # To prevent that block from being called anymore, just unsubscribe passing
+ # that reference:
+ #
+ # ActiveSupport::Notifications.unsubscribe(subscriber)
+ #
+ # == Default Queue
+ #
# Notifications ships with a queue implementation that consumes and publish events
# to log subscribers in a thread. You can use any queue implementation you want.
#
@@ -94,6 +128,13 @@ def subscribe(*args, &block)
end
end
+ def subscribed(callback, *args, &block)
+ subscriber = subscribe(*args, &callback)
+ yield
+ ensure
+ unsubscribe(subscriber)
+ end
+
def unsubscribe(args)
notifier.unsubscribe(args)
@instrumenters.clear
View
20 activesupport/test/notifications_test.rb
@@ -24,6 +24,26 @@ def event(*args)
end
end
+ class SubscribedTest < TestCase
+ def test_subscribed
+ name = "foo"
+ name2 = name * 2
+ expected = [name, name]
+
+ events = []
+ callback = lambda {|*_| events << _.first}
+ ActiveSupport::Notifications.subscribed(callback, name) do
+ ActiveSupport::Notifications.instrument(name)
+ ActiveSupport::Notifications.instrument(name2)
+ ActiveSupport::Notifications.instrument(name)
+ end
+ assert_equal expected, events
+
+ ActiveSupport::Notifications.instrument(name)
+ assert_equal expected, events
+ end
+ end
+
class UnsubscribeTest < TestCase
def test_unsubscribing_removes_a_subscription
@notifier.publish :foo

1 comment on commit d287e90

@jodosha

+1

Please sign in to comment.