diff options
Diffstat (limited to 'activesupport/lib')
-rw-r--r-- | activesupport/lib/active_support/callbacks.rb | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index e772a297fc..e3e1845868 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -134,6 +134,10 @@ module ActiveSupport @kind == _kind && @filter == _filter end + def duplicates?(other) + matches?(other.kind, other.filter) + end + def _update_filter(filter_options, new_options) filter_options[:if].concat(Array(new_options[:unless])) if new_options.key?(:unless) filter_options[:unless].concat(Array(new_options[:if])) if new_options.key?(:if) @@ -328,6 +332,30 @@ module ActiveSupport method.join("\n") end + def append(*callbacks) + callbacks.each { |c| append_one(c) } + end + + def prepend(*callbacks) + callbacks.each { |c| prepend_one(c) } + end + + private + + def append_one(callback) + remove_duplicates(callback) + push(callback) + end + + def prepend_one(callback) + remove_duplicates(callback) + unshift(callback) + end + + def remove_duplicates(callback) + delete_if { |c| callback.duplicates?(c) } + end + end module ClassMethods @@ -421,11 +449,7 @@ module ActiveSupport Callback.new(chain, filter, type, options.dup, self) end - filters.each do |filter| - chain.delete_if {|c| c.matches?(type, filter) } - end - - options[:prepend] ? chain.unshift(*(mapped.reverse)) : chain.push(*mapped) + options[:prepend] ? chain.prepend(*mapped) : chain.append(*mapped) target.send("_#{name}_callbacks=", chain) end |