aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2012-12-21 17:39:03 -0300
committerRafael Mendonça França <rafaelmfranca@gmail.com>2012-12-21 17:39:03 -0300
commitecc77515754b15e5a2d794832ec4a5286cabdfe5 (patch)
treeee40fb03408f925bc169dc8fba0751b926d28912 /activesupport/lib
parentbda1937f285d3114c2b2300b86c23f19db88de79 (diff)
parent4a9644a0d94a88896e1ebd3329b8f796fbd053d1 (diff)
downloadrails-ecc77515754b15e5a2d794832ec4a5286cabdfe5.tar.gz
rails-ecc77515754b15e5a2d794832ec4a5286cabdfe5.tar.bz2
rails-ecc77515754b15e5a2d794832ec4a5286cabdfe5.zip
Merge pull request #7376 from dmitriy-kiriyenko/fix-double-callback-in-same-statement
Prevent callback from being set twice. Conflicts: activesupport/CHANGELOG.md
Diffstat (limited to 'activesupport/lib')
-rw-r--r--activesupport/lib/active_support/callbacks.rb34
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