lib/active_support/callbacks.rb in activesupport-7.0.0.alpha2 vs lib/active_support/callbacks.rb in activesupport-7.0.0.rc1

- old
+ new

@@ -370,63 +370,160 @@ end end # A future invocation of user-supplied code (either as a callback, # or a condition filter). - class CallTemplate # :nodoc: - def initialize(target, method, arguments, block) - @override_target = target - @method_name = method - @arguments = arguments - @override_block = block + module CallTemplate # :nodoc: + class MethodCall + def initialize(method) + @method_name = method + end + + # Return the parts needed to make this call, with the given + # input values. + # + # Returns an array of the form: + # + # [target, block, method, *arguments] + # + # This array can be used as such: + # + # target.send(method, *arguments, &block) + # + # The actual invocation is left up to the caller to minimize + # call stack pollution. + def expand(target, value, block) + [target, block, @method_name] + end + + def make_lambda + lambda do |target, value, &block| + target.send(@method_name, &block) + end + end + + def inverted_lambda + lambda do |target, value, &block| + !target.send(@method_name, &block) + end + end end - # Return the parts needed to make this call, with the given - # input values. - # - # Returns an array of the form: - # - # [target, block, method, *arguments] - # - # This array can be used as such: - # - # target.send(method, *arguments, &block) - # - # The actual invocation is left up to the caller to minimize - # call stack pollution. - def expand(target, value, block) - expanded = [@override_target || target, @override_block || block, @method_name] + class ObjectCall + def initialize(target, method) + @override_target = target + @method_name = method + end - @arguments.each do |arg| - case arg - when :value then expanded << value - when :target then expanded << target - when :block then expanded << (block || raise(ArgumentError)) + def expand(target, value, block) + [@override_target || target, block, @method_name, target] + end + + def make_lambda + lambda do |target, value, &block| + (@override_target || target).send(@method_name, target, &block) end end - expanded + def inverted_lambda + lambda do |target, value, &block| + !(@override_target || target).send(@method_name, target, &block) + end + end end - # Return a lambda that will make this call when given the input - # values. - def make_lambda - lambda do |target, value, &block| - target, block, method, *arguments = expand(target, value, block) - target.send(method, *arguments, &block) + class InstanceExec0 + def initialize(block) + @override_block = block end + + def expand(target, value, block) + [target, @override_block, :instance_exec] + end + + def make_lambda + lambda do |target, value, &block| + target.instance_exec(&@override_block) + end + end + + def inverted_lambda + lambda do |target, value, &block| + !target.instance_exec(&@override_block) + end + end end - # Return a lambda that will make this call when given the input - # values, but then return the boolean inverse of that result. - def inverted_lambda - lambda do |target, value, &block| - target, block, method, *arguments = expand(target, value, block) - ! target.send(method, *arguments, &block) + class InstanceExec1 + def initialize(block) + @override_block = block end + + def expand(target, value, block) + [target, @override_block, :instance_exec, target] + end + + def make_lambda + lambda do |target, value, &block| + target.instance_exec(target, &@override_block) + end + end + + def inverted_lambda + lambda do |target, value, &block| + !target.instance_exec(target, &@override_block) + end + end end + class InstanceExec2 + def initialize(block) + @override_block = block + end + + def expand(target, value, block) + raise ArgumentError unless block + [target, @override_block || block, :instance_exec, target, block] + end + + def make_lambda + lambda do |target, value, &block| + raise ArgumentError unless block + target.instance_exec(target, block, &@override_block) + end + end + + def inverted_lambda + lambda do |target, value, &block| + raise ArgumentError unless block + !target.instance_exec(target, block, &@override_block) + end + end + end + + class ProcCall + def initialize(target) + @override_target = target + end + + def expand(target, value, block) + [@override_target || target, block, :call, target, value] + end + + def make_lambda + lambda do |target, value, &block| + (@override_target || target).call(target, value, &block) + end + end + + def inverted_lambda + lambda do |target, value, &block| + !(@override_target || target).call(target, value, &block) + end + end + end + # Filters support: # # Symbols:: A method to call. # Procs:: A proc to call with the object. # Objects:: An object with a <tt>before_foo</tt> method on it to call. @@ -434,25 +531,23 @@ # All of these objects are converted into a CallTemplate and handled # the same after this point. def self.build(filter, callback) case filter when Symbol - new(nil, filter, [], nil) + MethodCall.new(filter) when Conditionals::Value - new(filter, :call, [:target, :value], nil) + ProcCall.new(filter) when ::Proc if filter.arity > 1 - new(nil, :instance_exec, [:target, :block], filter) + InstanceExec2.new(filter) elsif filter.arity > 0 - new(nil, :instance_exec, [:target], filter) + InstanceExec1.new(filter) else - new(nil, :instance_exec, [], filter) + InstanceExec0.new(filter) end else - method_to_call = callback.current_scopes.join("_") - - new(filter, method_to_call, [:target], nil) + ObjectCall.new(filter, callback.current_scopes.join("_").to_sym) end end end # Execute before and after filters in a sequence instead of @@ -606,11 +701,11 @@ end # This is used internally to append, prepend and skip callbacks to the # CallbackChain. def __update_callbacks(name) # :nodoc: - ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse_each do |target| + ([self] + self.descendants).reverse_each do |target| chain = target.get_callbacks name yield target, chain.dup end end @@ -730,11 +825,11 @@ # Remove all set callbacks for the given event. def reset_callbacks(name) callbacks = get_callbacks name - ActiveSupport::DescendantsTracker.descendants(self).each do |target| + self.descendants.each do |target| chain = target.get_callbacks(name).dup callbacks.each { |c| chain.delete(c) } target.set_callbacks name, chain end @@ -823,10 +918,10 @@ options = names.extract_options! names.each do |name| name = name.to_sym - ([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target| + ([self] + self.descendants).each do |target| target.set_callbacks name, CallbackChain.new(name, options) end module_eval <<-RUBY, __FILE__, __LINE__ + 1 def _run_#{name}_callbacks(&block)