From e377228342e0185ef77ad8a58a8df4ece1683e80 Mon Sep 17 00:00:00 2001 From: Ben McRedmond Date: Wed, 2 Jan 2013 11:53:37 +0000 Subject: 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?`. --- activesupport/lib/active_support/callbacks.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 6c0cae71ed..4a3636eb56 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -131,6 +131,7 @@ module ActiveSupport end def matches?(_kind, _filter) + _filter = _method_name_for_object_filter(_kind, _filter) if @_is_object_filter @kind == _kind && @filter == _filter end @@ -234,6 +235,14 @@ module ActiveSupport @compiled_options = conditions.flatten.join(" && ") end + def _method_name_for_object_filter(kind, filter) + class_name = filter.kind_of?(Class) ? filter.to_s : filter.class.to_s + class_name.gsub!(/<|>|#/, '') + class_name.gsub!(/\/|:/, "_") + + "_callback_#{kind}_#{class_name}" + end + # Filters support: # # Arrays:: Used in conditions. This is used to specify @@ -255,6 +264,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 +280,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) -- cgit v1.2.3