Subscriber.attach_to with inherit_all option
This commit is contained in:
parent
82217c2170
commit
387aa8c373
|
@ -1,3 +1,38 @@
|
|||
* ActiveSupport::Subscriber#attach_to now accepts an inherit_from: argument. When set to true,
|
||||
it allows a subscriber to receive events for methods defined in the subscriber's ancestor class(es)
|
||||
|
||||
```ruby
|
||||
class ActionControllerSubscriber < ActiveSupport::Subscriber
|
||||
attach_to :action_controller
|
||||
|
||||
def start_processing(event)
|
||||
info "Processing by #{event.payload[:controller]}##{event.payload[:action]} as #{format}"
|
||||
end
|
||||
|
||||
def redirect_to(event)
|
||||
info { "Redirected to #{event.payload[:location]}" }
|
||||
end
|
||||
end
|
||||
|
||||
# We detach ActionControllerSubscriber from the :action_controller namespace so that our CustomActionControllerSubscriber
|
||||
# can provide its own instrumentation for certain events in the namespace
|
||||
ActionControllerSubscriber.detach_from(:action_controller)
|
||||
|
||||
class CustomActionControllerSubscriber < ActionControllerSubscriber
|
||||
attach_to :action_controller, inherit_all: true
|
||||
|
||||
def start_processing(event)
|
||||
info "A custom response to start_processing events"
|
||||
end
|
||||
|
||||
# => CustomActionControllerSubscriber will process events for "start_processing.action_controller" notifications
|
||||
# using its own #start_processing implementation, while retaining ActionControllerSubscriber's instrumentation
|
||||
# for "redirect_to.action_controller" notifications
|
||||
end
|
||||
```
|
||||
|
||||
*Adrianna Chang*
|
||||
|
||||
* Fix bug to make memcached write_entry expire correctly with unless_exist
|
||||
|
||||
*Jye Lee*
|
||||
|
|
|
@ -96,6 +96,11 @@ module ActiveSupport
|
|||
def flush_all!
|
||||
logger.flush if logger.respond_to?(:flush)
|
||||
end
|
||||
|
||||
private
|
||||
def fetch_public_methods(subscriber, inherit_all)
|
||||
subscriber.public_methods(inherit_all) - LogSubscriber.public_instance_methods(true)
|
||||
end
|
||||
end
|
||||
|
||||
def logger
|
||||
|
|
|
@ -31,15 +31,16 @@ module ActiveSupport
|
|||
class Subscriber
|
||||
class << self
|
||||
# Attach the subscriber to a namespace.
|
||||
def attach_to(namespace, subscriber = new, notifier = ActiveSupport::Notifications)
|
||||
def attach_to(namespace, subscriber = new, notifier = ActiveSupport::Notifications, inherit_all: false)
|
||||
@namespace = namespace
|
||||
@subscriber = subscriber
|
||||
@notifier = notifier
|
||||
@inherit_all = inherit_all
|
||||
|
||||
subscribers << subscriber
|
||||
|
||||
# Add event subscribers for all existing methods on the class.
|
||||
subscriber.public_methods(false).each do |event|
|
||||
fetch_public_methods(subscriber, inherit_all).each do |event|
|
||||
add_event_subscriber(event)
|
||||
end
|
||||
end
|
||||
|
@ -55,7 +56,7 @@ module ActiveSupport
|
|||
subscribers.delete(subscriber)
|
||||
|
||||
# Remove event subscribers of all existing methods on the class.
|
||||
subscriber.public_methods(false).each do |event|
|
||||
fetch_public_methods(subscriber, true).each do |event|
|
||||
remove_event_subscriber(event)
|
||||
end
|
||||
|
||||
|
@ -117,6 +118,10 @@ module ActiveSupport
|
|||
def pattern_subscribed?(pattern)
|
||||
subscriber.patterns.key?(pattern)
|
||||
end
|
||||
|
||||
def fetch_public_methods(subscriber, inherit_all)
|
||||
subscriber.public_methods(inherit_all) - Subscriber.public_instance_methods(true)
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :patterns # :nodoc:
|
||||
|
|
|
@ -4,8 +4,6 @@ require_relative "abstract_unit"
|
|||
require "active_support/subscriber"
|
||||
|
||||
class TestSubscriber < ActiveSupport::Subscriber
|
||||
attach_to :doodle
|
||||
|
||||
cattr_reader :events
|
||||
|
||||
def self.clear
|
||||
|
@ -16,23 +14,19 @@ class TestSubscriber < ActiveSupport::Subscriber
|
|||
events << event
|
||||
end
|
||||
|
||||
def another_open_party(event)
|
||||
events << event
|
||||
end
|
||||
|
||||
private
|
||||
def private_party(event)
|
||||
events << event
|
||||
end
|
||||
end
|
||||
|
||||
class TestSubscriber2 < ActiveSupport::Subscriber
|
||||
attach_to :doodle
|
||||
detach_from :doodle
|
||||
|
||||
cattr_reader :events
|
||||
|
||||
def self.clear
|
||||
@@events = []
|
||||
end
|
||||
|
||||
def open_party(event)
|
||||
class PartySubscriber < TestSubscriber
|
||||
def another_open_party(event)
|
||||
event.payload["processing_class"] = self.class
|
||||
events << event
|
||||
end
|
||||
end
|
||||
|
@ -48,31 +42,77 @@ end
|
|||
class SubscriberTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
TestSubscriber.clear
|
||||
TestSubscriber2.clear
|
||||
end
|
||||
|
||||
def test_attaches_subscribers
|
||||
TestSubscriber.attach_to :doodle
|
||||
|
||||
ActiveSupport::Notifications.instrument("open_party.doodle")
|
||||
|
||||
assert_equal "open_party.doodle", TestSubscriber.events.first.name
|
||||
ensure
|
||||
TestSubscriber.detach_from :doodle
|
||||
end
|
||||
|
||||
def test_attaches_subscribers_with_inherit_all_option
|
||||
PartySubscriber.attach_to :doodle, inherit_all: true
|
||||
|
||||
ActiveSupport::Notifications.instrument("open_party.doodle")
|
||||
|
||||
assert_equal "open_party.doodle", PartySubscriber.events.first.name
|
||||
ensure
|
||||
PartySubscriber.detach_from :doodle
|
||||
end
|
||||
|
||||
def test_attaches_subscribers_with_inherit_all_option_replaces_original_behaviour
|
||||
PartySubscriber.attach_to :doodle, inherit_all: true
|
||||
|
||||
ActiveSupport::Notifications.instrument("another_open_party.doodle")
|
||||
|
||||
assert_equal 1, PartySubscriber.events.size
|
||||
|
||||
event = PartySubscriber.events.first
|
||||
assert_equal "another_open_party.doodle", event.name
|
||||
assert_equal PartySubscriber, event.payload.fetch("processing_class")
|
||||
ensure
|
||||
PartySubscriber.detach_from :doodle
|
||||
end
|
||||
|
||||
def test_attaches_only_one_subscriber
|
||||
TestSubscriber.attach_to :doodle
|
||||
|
||||
ActiveSupport::Notifications.instrument("open_party.doodle")
|
||||
|
||||
assert_equal 1, TestSubscriber.events.size
|
||||
ensure
|
||||
TestSubscriber.detach_from :doodle
|
||||
end
|
||||
|
||||
def test_does_not_attach_private_methods
|
||||
TestSubscriber.attach_to :doodle
|
||||
|
||||
ActiveSupport::Notifications.instrument("private_party.doodle")
|
||||
|
||||
assert_equal [], TestSubscriber.events
|
||||
ensure
|
||||
TestSubscriber.detach_from :doodle
|
||||
end
|
||||
|
||||
def test_detaches_subscribers
|
||||
TestSubscriber.attach_to :doodle
|
||||
TestSubscriber.detach_from :doodle
|
||||
|
||||
ActiveSupport::Notifications.instrument("open_party.doodle")
|
||||
|
||||
assert_equal [], TestSubscriber.events
|
||||
end
|
||||
|
||||
def test_detaches_subscribers
|
||||
def test_detaches_subscribers_from_inherited_methods
|
||||
PartySubscriber.attach_to :doodle
|
||||
PartySubscriber.detach_from :doodle
|
||||
|
||||
ActiveSupport::Notifications.instrument("open_party.doodle")
|
||||
|
||||
assert_equal [], TestSubscriber2.events
|
||||
assert_equal 1, TestSubscriber.events.size
|
||||
assert_equal [], TestSubscriber.events
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue