aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
authorBen McRedmond <ben@benmcredmond.com>2013-01-02 11:53:37 +0000
committerBen McRedmond <ben@benmcredmond.com>2013-04-04 16:11:13 -0700
commit8e1d3cd4909c83bbceb7df00da71ec1393a90f6e (patch)
tree1a6c8b34790da17cb52262aaf02f753d4f136691 /activesupport/lib/active_support
parente456ad514aca81cbcb67ea9d919730ac00724a38 (diff)
downloadrails-8e1d3cd4909c83bbceb7df00da71ec1393a90f6e.tar.gz
rails-8e1d3cd4909c83bbceb7df00da71ec1393a90f6e.tar.bz2
rails-8e1d3cd4909c83bbceb7df00da71ec1393a90f6e.zip
Fixes skipping object callback filters
This allows you to skip callbacks that are defined by objects, e.g. for `ActionController`: skip_after_filter MySpecialFilter Previously this didn't work due to a bug in how Rails compared callbacks in `Callback#matches?`. When a callback is compiled, if it's an object filter (i.e. not a method, proc, etc.), `Callback` now defines a method on `@klass` that is derived from the class name rather than `@callback_id`. So, when `skip_callback` tries to find the appropriate callback to remove, `Callback` can regenerate the method name for the filter object and return the correct value for `Callback#matches?`.
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/callbacks.rb25
1 files changed, 23 insertions, 2 deletions
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 6c0cae71ed..e81686b3a6 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -131,7 +131,15 @@ module ActiveSupport
end
def matches?(_kind, _filter)
- @kind == _kind && @filter == _filter
+ _filter_matches = false
+
+ if @_is_object_filter
+ _filter_matches = @filter.to_s.start_with?(_method_name_for_object_filter(_kind, _filter, false))
+ else
+ _filter_matches = (@filter == _filter)
+ end
+
+ @kind == _kind && _filter_matches
end
def duplicates?(other)
@@ -234,6 +242,16 @@ module ActiveSupport
@compiled_options = conditions.flatten.join(" && ")
end
+ def _method_name_for_object_filter(kind, filter, append_next_id = true)
+ class_name = filter.kind_of?(Class) ? filter.to_s : filter.class.to_s
+ class_name.gsub!(/<|>|#/, '')
+ class_name.gsub!(/\/|:/, "_")
+
+ method_name = "_callback_#{kind}_#{class_name}"
+ method_name << "_#{next_id}" if append_next_id
+ method_name
+ end
+
# Filters support:
#
# Arrays:: Used in conditions. This is used to specify
@@ -255,6 +273,8 @@ module ActiveSupport
# a method is created that calls the before_foo method
# on the object.
def _compile_filter(filter)
+ @_is_object_filter = false
+
case filter
when Array
filter.map {|f| _compile_filter(f)}
@@ -269,7 +289,8 @@ module ActiveSupport
method_name << (filter.arity == 1 ? "(self)" : " self, Proc.new ")
else
- method_name = "_callback_#{@kind}_#{next_id}"
+ method_name = _method_name_for_object_filter(kind, filter)
+ @_is_object_filter = true
@klass.send(:define_method, "#{method_name}_object") { filter }
_normalize_legacy_filter(kind, filter)