From fef22157b07f101229d29544d578bfe2cb9fedfe Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Thu, 28 Apr 2011 08:27:15 -0700 Subject: Fix bug with AM::Observer disablement. Now that we propagate the enabling/disabling to descendants, we no longer have to check the disabled_observer Set on each superclass of the model class. This was causing a bug when disabling all observers at a superclass level and then enabling an individual observer at a subclass level. Plus the logic is simpler now :). --- activemodel/lib/active_model/observer_array.rb | 30 +++++++------------------- activemodel/lib/active_model/observing.rb | 12 ++++++++--- activemodel/test/cases/observer_array_test.rb | 10 +++++++++ 3 files changed, 27 insertions(+), 25 deletions(-) (limited to 'activemodel') diff --git a/activemodel/lib/active_model/observer_array.rb b/activemodel/lib/active_model/observer_array.rb index d501215dd6..ab7f86007f 100644 --- a/activemodel/lib/active_model/observer_array.rb +++ b/activemodel/lib/active_model/observer_array.rb @@ -4,34 +4,16 @@ module ActiveModel # Stores the enabled/disabled state of individual observers for # a particular model classes. class ObserverArray < Array - # returns false if: - # - the ObserverArray for the given model's class has the given observer - # in its disabled_observers set. - # - or that is the case at any level of the model's superclass chain. - def self.observer_enabled?(observer, model) - klass = model.class - observer_class = observer.class - - loop do - break unless klass.respond_to?(:observers) - array = klass.observers - return false if array.disabled_observers.include?(observer_class) - klass = klass.superclass - end - - true # observers are enabled by default - end - - def disabled_observers - @disabled_observers ||= Set.new - end - attr_reader :model_class def initialize(model_class, *args) @model_class = model_class super(*args) end + def disabled_for?(observer) + disabled_observers.include?(observer.class) + end + def disable(*observers, &block) set_enablement(false, observers, &block) end @@ -42,6 +24,10 @@ module ActiveModel protected + def disabled_observers + @disabled_observers ||= Set.new + end + def observer_class_for(observer) return observer if observer.is_a?(Class) diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index 9ffcda8dd7..c1ac4eb4af 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -222,9 +222,9 @@ module ActiveModel # Send observed_method(object) if the method exists. def update(observed_method, object) #:nodoc: - if respond_to?(observed_method) && ObserverArray.observer_enabled?(self, object) - send(observed_method, object) - end + return unless respond_to?(observed_method) + return if disabled_for?(object) + send(observed_method, object) end # Special method sent by the observed class when it is inherited. @@ -238,5 +238,11 @@ module ActiveModel def add_observer!(klass) #:nodoc: klass.add_observer(self) end + + def disabled_for?(object) + klass = object.class + return false unless klass.respond_to?(:observers) + klass.observers.disabled_for?(self) + end end end diff --git a/activemodel/test/cases/observer_array_test.rb b/activemodel/test/cases/observer_array_test.rb index 38e4fd59fc..3ede5682b4 100644 --- a/activemodel/test/cases/observer_array_test.rb +++ b/activemodel/test/cases/observer_array_test.rb @@ -65,6 +65,16 @@ class ObserverArrayTest < ActiveModel::TestCase assert_observer_notified Budget, AuditTrail end + test "can enable observers on individual models without affecting those observers on other models" do + ORM.observers.disable :all + Budget.observers.enable AuditTrail + + assert_observer_not_notified Widget, WidgetObserver + assert_observer_not_notified Budget, BudgetObserver + assert_observer_not_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + test "can disable observers for the duration of a block" do yielded = false ORM.observers.disable :budget_observer do -- cgit v1.2.3