aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
authorMyron Marston <myron.marston@gmail.com>2011-04-28 07:35:55 +0800
committerDavid Heinemeier Hansson <david@loudthinking.com>2011-04-28 10:25:07 +0800
commitad62f1928768bd2676958a4a08512bad342fe469 (patch)
tree473e3c3f4a84f9f8ac5a629421198fa83b97a606 /activemodel
parent1f8cc446d9a7ab751a2def65309ac4bc71e85cd3 (diff)
downloadrails-ad62f1928768bd2676958a4a08512bad342fe469.tar.gz
rails-ad62f1928768bd2676958a4a08512bad342fe469.tar.bz2
rails-ad62f1928768bd2676958a4a08512bad342fe469.zip
Handle enabling/disabling observers at different levels of the class hierarchy.
Last call wins.
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/lib/active_model/observer_array.rb34
-rw-r--r--activemodel/lib/active_model/observing.rb5
-rw-r--r--activemodel/test/cases/observer_array_test.rb39
3 files changed, 75 insertions, 3 deletions
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