Allow ActiveRecord observers to be disabled.

We have to use Observer#update rather than Observer#send since the enabled state is checked in #update before forwarding the method call on.
This commit is contained in:
Myron Marston 2011-08-12 19:58:37 -07:00
parent 943a37348a
commit d3c15a1d31
4 changed files with 27 additions and 3 deletions

View File

@ -226,10 +226,10 @@ module ActiveModel
# Send observed_method(object) if the method exists and
# the observer is enabled for the given object's class.
def update(observed_method, object) #:nodoc:
def update(observed_method, object, &block) #:nodoc:
return unless respond_to?(observed_method)
return if disabled_for?(object)
send(observed_method, object)
send(observed_method, object, &block)
end
# Special method sent by the observed class when it is inherited.

View File

@ -17,6 +17,10 @@ class FooObserver < ActiveModel::Observer
def on_spec(record)
stub.event_with(record) if stub
end
def around_save(record)
yield :in_around_save
end
end
class Foo
@ -133,4 +137,12 @@ class ObserverTest < ActiveModel::TestCase
foo = Foo.new
Foo.send(:notify_observers, :whatever, foo)
end
test "update passes a block on to the observer" do
yielded_value = nil
FooObserver.instance.update(:around_save, Foo.new) do |val|
yielded_value = val
end
assert_equal :in_around_save, yielded_value
end
end

View File

@ -111,7 +111,7 @@ module ActiveRecord
callback_meth = :"_notify_#{observer_name}_for_#{callback}"
unless klass.respond_to?(callback_meth)
klass.send(:define_method, callback_meth) do |&block|
observer.send(callback, self, &block)
observer.update(callback, self, &block)
end
klass.send(callback, callback_meth)
end

View File

@ -231,6 +231,18 @@ class LifecycleTest < ActiveRecord::TestCase
assert_not_nil observer.topic_ids.last
end
test "able to disable observers" do
observer = DeveloperObserver.instance # activate
observer.calls.clear
ActiveRecord::Base.observers.disable DeveloperObserver do
Developer.create! :name => 'Ancestor', :salary => 100000
SpecialDeveloper.create! :name => 'Descendent', :salary => 100000
end
assert_equal [], observer.calls
end
def test_observer_is_called_once
observer = DeveloperObserver.instance # activate
observer.calls.clear