diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 0548284186..96cf0d5654 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -92,20 +92,11 @@ module ActiveSupport @@_callback_sequence = 0 class Basic < Callback - def matches?(_kind, _filter) - super && @filter == _filter - end end class Object < Callback - def matches?(_kind, _filter) - return false unless super - - if !_filter.is_a?(String) - @filter.to_s.start_with?(_method_name_for_object_filter(_kind, _filter, false)) - else - @filter == _filter - end + def duplicates?(other) + false end end @@ -127,7 +118,8 @@ module ActiveSupport normalize_options!(options) @raw_filter, @options = filter, options - @filter = _compile_filter(filter) + @filter = _compile_filter(filter) + @source = _compile_source(filter) recompile_options! end @@ -161,7 +153,7 @@ module ActiveSupport end def matches?(_kind, _filter) - @kind == _kind + @kind == _kind && filter == _filter end def duplicates?(other) @@ -191,7 +183,7 @@ module ActiveSupport # This double assignment is to prevent warnings in 1.9.3 as # the `result` variable is not always used except if the # terminator code refers to it. - result = result = #{@filter} + result = result = #{@source} halted = (#{chain.config[:terminator]}) if halted halted_callback_hook(#{@raw_filter.inspect.inspect}) @@ -203,7 +195,7 @@ module ActiveSupport <<-RUBY_EVAL #{code} if #{!chain.config[:skip_after_callbacks_if_terminated] || "!halted"} && #{@compiled_options} - #{@filter} + #{@source} end RUBY_EVAL when :around @@ -238,7 +230,7 @@ module ActiveSupport @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{name}(halted) if #{@compiled_options} && !halted - #{@filter} do + #{@source} do yield self end else @@ -256,11 +248,11 @@ module ActiveSupport conditions = ["true"] unless options[:if].empty? - conditions << Array(_compile_filter(options[:if])) + conditions << Array(_compile_source(options[:if])) end unless options[:unless].empty? - conditions << Array(_compile_filter(options[:unless])).map {|f| "!#{f}"} + conditions << Array(_compile_source(options[:unless])).map {|f| "!#{f}"} end @compiled_options = conditions.flatten.join(" && ") @@ -276,6 +268,25 @@ module ActiveSupport method_name end + def _compile_filter(filter) + case filter + when Array + filter.map {|f| _compile_filter(f)} + when Symbol + filter + when String + "(#{filter})" + when Proc + method_name = "_callback_#{@kind}_#{next_id}" + @klass.send(:define_method, method_name, &filter) + return method_name if filter.arity <= 0 + + method_name << (filter.arity == 1 ? "(self)" : " self, Proc.new ") + else + filter + end + end + # Filters support: # # Arrays:: Used in conditions. This is used to specify @@ -296,10 +307,10 @@ module ActiveSupport # Objects:: # a method is created that calls the before_foo method # on the object. - def _compile_filter(filter) + def _compile_source(filter) case filter when Array - filter.map {|f| _compile_filter(f)} + filter.map {|f| _compile_source(f)} when Symbol filter when String