Skip to content
This repository
Browse code

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

  • Loading branch information...
commit 1a3fe8ce42e202630e6b1d8cf7137002e270ebdb 1 parent 46f6a2e
Rolf Timmermans authored josevalim committed
2  activesupport/lib/active_support/callbacks.rb
@@ -416,7 +416,7 @@ def __update_callbacks(name, filters = [], block = nil) #:nodoc:
416 416 options = filters.last.is_a?(Hash) ? filters.pop : {}
417 417 filters.unshift(block) if block
418 418
419   - ([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target|
  419 + ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse.each do |target|
420 420 chain = target.send("_#{name}_callbacks")
421 421 yield target, chain.dup, type, filters, options
422 422 target.__define_runner(name)
30 activesupport/test/callback_inheritance_test.rb
@@ -82,6 +82,30 @@ def do_nothing
82 82 end
83 83 end
84 84
  85 +class CountingParent
  86 + include ActiveSupport::Callbacks
  87 +
  88 + attr_reader :count
  89 +
  90 + define_callbacks :dispatch
  91 +
  92 + def initialize
  93 + @count = 0
  94 + end
  95 +
  96 + def count!
  97 + @count += 1
  98 + end
  99 +
  100 + def dispatch
  101 + run_callbacks(:dispatch)
  102 + self
  103 + end
  104 +end
  105 +
  106 +class CountingChild < CountingParent
  107 +end
  108 +
85 109 class BasicCallbacksTest < Test::Unit::TestCase
86 110 def setup
87 111 @index = GrandParent.new("index").dispatch
@@ -147,4 +171,10 @@ def test_callbacks_looks_to_the_superclass_before_running
147 171 child = EmptyChild.new.dispatch
148 172 assert child.performed?
149 173 end
  174 +
  175 + def test_callbacks_should_be_performed_once_in_child_class
  176 + CountingParent.set_callback(:dispatch, :before) { count! }
  177 + child = CountingChild.new.dispatch
  178 + assert_equal 1, child.count
  179 + end
150 180 end

0 comments on commit 1a3fe8c

Please sign in to comment.
Something went wrong with that request. Please try again.