Permalink
Browse files

Fix observer callbacks firing multiple times on descendant instances

  • Loading branch information...
1 parent 3265bbb commit 6ba8caf3ee239fd7010b18ff251cb5c2d52b48c4 @kamal kamal committed with tenderlove Feb 9, 2011
Showing with 22 additions and 1 deletion.
  1. +8 −1 activerecord/lib/active_record/observer.rb
  2. +14 −0 activerecord/test/cases/lifecycle_test.rb
@@ -104,10 +104,17 @@ def add_observer!(klass)
def define_callbacks(klass)
observer = self
+ observer_name = observer.class.name.underscore.gsub('/', '__')
ActiveRecord::Callbacks::CALLBACKS.each do |callback|
next unless respond_to?(callback)
- klass.send(callback){|record| observer.send(callback, record)}
+ callback_meth = :"_notify_#{observer_name}_for_#{callback}"
+ unless klass.respond_to?(callback_meth)
+ klass.send(:define_method, callback_meth) do
+ observer.send(callback, self)
+ end
+ klass.send(callback, callback_meth)
+ end
end
end
end
@@ -7,6 +7,12 @@
class SpecialDeveloper < Developer; end
+class DeveloperObserver < ActiveRecord::Observer
+ def before_save(developer)
+ developer.salary += 1
+ end
+end
+
class SalaryChecker < ActiveRecord::Observer
observe :special_developer
attr_accessor :last_saved
@@ -196,4 +202,12 @@ def test_invalid_observer
assert_equal developer, SalaryChecker.instance.last_saved
end
+ test "callback observing the ancestor does not fire multiple times on descendent" do
+ DeveloperObserver.instance # activate
+ developer = Developer.create! :name => 'Ancestor', :salary => 100000
+ assert_equal 100001, developer.salary, 'ancestor callback fired multiple times'
+ developer = SpecialDeveloper.create! :name => 'Descendent', :salary => 100000
+ assert_equal 100001, developer.salary, 'descendent callback fired multiple times'
+ end
+
end

0 comments on commit 6ba8caf

Please sign in to comment.