Skip to content

Commit

Permalink
Fix observer callbacks firing multiple times on descendant instances
Browse files Browse the repository at this point in the history
  • Loading branch information
kamal authored and tenderlove committed Feb 23, 2011
1 parent 30a0e3f commit ee491b0
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
9 changes: 8 additions & 1 deletion activerecord/lib/active_record/observer.rb
Expand Up @@ -108,10 +108,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
Expand Down
14 changes: 14 additions & 0 deletions activerecord/test/cases/lifecycle_test.rb
Expand Up @@ -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
Expand Down Expand Up @@ -195,4 +201,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 ee491b0

Please sign in to comment.