From 05d4653cef1c1d8d77228de26d55cf6d6a0ce20b Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Thu, 28 Apr 2011 07:58:58 -0700 Subject: Revert "Revert "Handle enabling/disabling observers at different levels of the class hierarchy."" This reverts commit 2a25c5818b03d7d6cd63aad180bff23479dbd861. I'm going to add another commit that keeps the same behavior of fixes the problems of leaking memory in development. --- activemodel/lib/active_model/observer_array.rb | 34 ++++++++++++++++++++-- activemodel/lib/active_model/observing.rb | 5 ++++ activemodel/test/cases/observer_array_test.rb | 39 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) (limited to 'activemodel') diff --git a/activemodel/lib/active_model/observer_array.rb b/activemodel/lib/active_model/observer_array.rb index b8aa9cc1e2..f3b5811b81 100644 --- a/activemodel/lib/active_model/observer_array.rb +++ b/activemodel/lib/active_model/observer_array.rb @@ -48,7 +48,7 @@ module ActiveModel set_enablement(true, observers, &block) end - private + protected def observer_class_for(observer) return observer if observer.is_a?(Class) @@ -61,13 +61,37 @@ module ActiveModel end end + def start_transaction + disabled_observer_stack.push(disabled_observers.dup) + each_subclass_array do |array| + array.start_transaction + end + end + + def disabled_observer_stack + @disabled_observer_stack ||= [] + end + + def end_transaction + @disabled_observers = disabled_observer_stack.pop + each_subclass_array do |array| + array.end_transaction + end + end + def transaction - orig_disabled_observers = disabled_observers.dup + start_transaction begin yield ensure - @disabled_observers = orig_disabled_observers + end_transaction + end + end + + def each_subclass_array + model_class.subclasses.each do |subclass| + yield self.class.for(subclass) end end @@ -92,6 +116,10 @@ module ActiveModel disabled_observers << klass end end + + each_subclass_array do |array| + array.set_enablement(enabled, observers) + end end end end diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index e1a2ce218d..ba6be46670 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -70,6 +70,10 @@ module ActiveModel observer_instances.size end + def subclasses + @subclasses ||= [] + end + protected def instantiate_observer(observer) #:nodoc: # string/symbol @@ -89,6 +93,7 @@ module ActiveModel # Notify observers when the observed class is subclassed. def inherited(subclass) super + subclasses << subclass notify_observers :observed_class_inherited, subclass end end diff --git a/activemodel/test/cases/observer_array_test.rb b/activemodel/test/cases/observer_array_test.rb index 215ca80bb4..38e4fd59fc 100644 --- a/activemodel/test/cases/observer_array_test.rb +++ b/activemodel/test/cases/observer_array_test.rb @@ -118,5 +118,44 @@ class ObserverArrayTest < ActiveModel::TestCase ORM.observers.disable Widget end end + + test "allows #enable at the superclass level to override #disable at the subclass level when called last" do + Widget.observers.disable :all + ORM.observers.enable :all + + assert_observer_notified Widget, WidgetObserver + assert_observer_notified Budget, BudgetObserver + assert_observer_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + + test "allows #disable at the superclass level to override #enable at the subclass level when called last" do + Budget.observers.enable :audit_trail + ORM.observers.disable :audit_trail + + assert_observer_notified Widget, WidgetObserver + assert_observer_notified Budget, BudgetObserver + assert_observer_not_notified Widget, AuditTrail + assert_observer_not_notified Budget, AuditTrail + end + + test "can use the block form at different levels of the hierarchy" do + yielded = false + Widget.observers.disable :all + + ORM.observers.enable :all do + yielded = true + assert_observer_notified Widget, WidgetObserver + assert_observer_notified Budget, BudgetObserver + assert_observer_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + + assert yielded + assert_observer_not_notified Widget, WidgetObserver + assert_observer_notified Budget, BudgetObserver + assert_observer_not_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end end -- cgit v1.2.3