Permalink
Browse files

Prevent callbacks in child classes from being executed more than once.

  • Loading branch information...
1 parent 46f6a2e commit 1a3fe8ce42e202630e6b1d8cf7137002e270ebdb Rolf Timmermans committed with josevalim Mar 12, 2011
Showing with 31 additions and 1 deletion.
  1. +1 −1 activesupport/lib/active_support/callbacks.rb
  2. +30 −0 activesupport/test/callback_inheritance_test.rb
@@ -416,7 +416,7 @@ def __update_callbacks(name, filters = [], block = nil) #:nodoc:
options = filters.last.is_a?(Hash) ? filters.pop : {}
filters.unshift(block) if block
- ([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target|
+ ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse.each do |target|
chain = target.send("_#{name}_callbacks")
yield target, chain.dup, type, filters, options
target.__define_runner(name)
@@ -82,6 +82,30 @@ def do_nothing
end
end
+class CountingParent
+ include ActiveSupport::Callbacks
+
+ attr_reader :count
+
+ define_callbacks :dispatch
+
+ def initialize
+ @count = 0
+ end
+
+ def count!
+ @count += 1
+ end
+
+ def dispatch
+ run_callbacks(:dispatch)
+ self
+ end
+end
+
+class CountingChild < CountingParent
+end
+
class BasicCallbacksTest < Test::Unit::TestCase
def setup
@index = GrandParent.new("index").dispatch
@@ -147,4 +171,10 @@ def test_callbacks_looks_to_the_superclass_before_running
child = EmptyChild.new.dispatch
assert child.performed?
end
+
+ def test_callbacks_should_be_performed_once_in_child_class
+ CountingParent.set_callback(:dispatch, :before) { count! }
+ child = CountingChild.new.dispatch
+ assert_equal 1, child.count
+ end
end

0 comments on commit 1a3fe8c

Please sign in to comment.