From 1f8cc446d9a7ab751a2def65309ac4bc71e85cd3 Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Thu, 28 Apr 2011 02:07:42 +0800 Subject: Allow observers to be enabled and disabled. This is useful in situations like model unit tests and the occasional rake task to backfill old data. --- activemodel/test/cases/observer_array_test.rb | 122 ++++++++++++++++++++++++++ activemodel/test/cases/observing_test.rb | 5 ++ activemodel/test/models/observers.rb | 27 ++++++ 3 files changed, 154 insertions(+) create mode 100644 activemodel/test/cases/observer_array_test.rb create mode 100644 activemodel/test/models/observers.rb (limited to 'activemodel/test') diff --git a/activemodel/test/cases/observer_array_test.rb b/activemodel/test/cases/observer_array_test.rb new file mode 100644 index 0000000000..215ca80bb4 --- /dev/null +++ b/activemodel/test/cases/observer_array_test.rb @@ -0,0 +1,122 @@ +require 'cases/helper' +require 'models/observers' + +class ObserverArrayTest < ActiveModel::TestCase + def teardown + ORM.observers.enable :all + Budget.observers.enable :all + Widget.observers.enable :all + end + + def assert_observer_notified(model_class, observer_class) + observer_class.instance.before_save_invocations.clear + model_instance = model_class.new + model_instance.save + assert_equal [model_instance], observer_class.instance.before_save_invocations + end + + def assert_observer_not_notified(model_class, observer_class) + observer_class.instance.before_save_invocations.clear + model_instance = model_class.new + model_instance.save + assert_equal [], observer_class.instance.before_save_invocations + end + + test "all observers are enabled by default" do + assert_observer_notified Widget, WidgetObserver + assert_observer_notified Budget, BudgetObserver + assert_observer_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + + test "can disable individual observers using a class constant" do + ORM.observers.disable WidgetObserver + + assert_observer_not_notified Widget, WidgetObserver + assert_observer_notified Budget, BudgetObserver + assert_observer_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + + test "can disable individual observers using a symbol" do + ORM.observers.disable :budget_observer + + assert_observer_notified Widget, WidgetObserver + assert_observer_not_notified Budget, BudgetObserver + assert_observer_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + + test "can disable all observers using :all" do + ORM.observers.disable :all + + assert_observer_not_notified Widget, WidgetObserver + assert_observer_not_notified Budget, BudgetObserver + assert_observer_not_notified Widget, AuditTrail + assert_observer_not_notified Budget, AuditTrail + end + + test "can disable observers on individual models without affecting observers on other models" do + Widget.observers.disable :all + + assert_observer_not_notified Widget, WidgetObserver + assert_observer_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 + yielded = true + assert_observer_notified Widget, WidgetObserver + assert_observer_not_notified Budget, BudgetObserver + assert_observer_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + + assert yielded + assert_observer_notified Widget, WidgetObserver + assert_observer_notified Budget, BudgetObserver + assert_observer_notified Widget, AuditTrail + assert_observer_notified Budget, AuditTrail + end + + test "can enable observers for the duration of a block" do + yielded = false + Widget.observers.disable :all + + Widget.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 + + test "raises an appropriate error when a developer accidentally enables or disables the wrong class (i.e. Widget instead of WidgetObserver)" do + assert_raise ArgumentError do + ORM.observers.enable :widget + end + + assert_raise ArgumentError do + ORM.observers.enable Widget + end + + assert_raise ArgumentError do + ORM.observers.disable :widget + end + + assert_raise ArgumentError do + ORM.observers.disable Widget + end + end +end + diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb index 63686843b6..99b1f407ae 100644 --- a/activemodel/test/cases/observing_test.rb +++ b/activemodel/test/cases/observing_test.rb @@ -43,6 +43,11 @@ class ObservingTest < ActiveModel::TestCase assert ObservedModel.observers.include?(:bar), ":bar not in #{ObservedModel.observers.inspect}" end + test "uses an ObserverArray so observers can be disabled" do + ObservedModel.observers = [:foo, :bar] + assert ObservedModel.observers.is_a?(ActiveModel::ObserverArray) + end + test "instantiates observer names passed as strings" do ObservedModel.observers << 'foo_observer' FooObserver.expects(:instance) diff --git a/activemodel/test/models/observers.rb b/activemodel/test/models/observers.rb new file mode 100644 index 0000000000..3729b3435e --- /dev/null +++ b/activemodel/test/models/observers.rb @@ -0,0 +1,27 @@ +class ORM + include ActiveModel::Observing + + def save + notify_observers :before_save + end + + class Observer < ActiveModel::Observer + def before_save_invocations + @before_save_invocations ||= [] + end + + def before_save(record) + before_save_invocations << record + end + end +end + +class Widget < ORM; end +class Budget < ORM; end +class WidgetObserver < ORM::Observer; end +class BudgetObserver < ORM::Observer; end +class AuditTrail < ORM::Observer + observe :widget, :budget +end + +ORM.instantiate_observers -- cgit v1.2.3