mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Optimize the performance of #delegate
Remove the use of #__send__ in order to boost performance. This also means that you can no longer delegate to private methods on the target object.
This commit is contained in:
parent
1db54dffaf
commit
1bac04e854
2 changed files with 32 additions and 9 deletions
|
@ -124,23 +124,27 @@ class Module
|
|||
file, line = caller.first.split(':', 2)
|
||||
line = line.to_i
|
||||
|
||||
if allow_nil
|
||||
methods.each do |method|
|
||||
methods.each do |method|
|
||||
method = method.to_s
|
||||
|
||||
# Attribute writer methods only accept one argument. Makes sure []=
|
||||
# methods still accept two arguments.
|
||||
definition = (method =~ /[^\]]=$/) ? "arg" : "*args, &block"
|
||||
|
||||
if allow_nil
|
||||
module_eval(<<-EOS, file, line - 2)
|
||||
def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block)
|
||||
def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
|
||||
if #{to} || #{to}.respond_to?(:#{method}) # if client || client.respond_to?(:name)
|
||||
#{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block)
|
||||
#{to}.#{method}(#{definition}) # client.name(*args, &block)
|
||||
end # end
|
||||
end # end
|
||||
EOS
|
||||
end
|
||||
else
|
||||
methods.each do |method|
|
||||
else
|
||||
exception = %(raise "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
|
||||
|
||||
module_eval(<<-EOS, file, line - 1)
|
||||
def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block)
|
||||
#{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block)
|
||||
def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
|
||||
#{to}.#{method}(#{definition}) # client.name(*args, &block)
|
||||
rescue NoMethodError # rescue NoMethodError
|
||||
if #{to}.nil? # if client.nil?
|
||||
#{exception} # # add helpful message to the exception
|
||||
|
|
|
@ -60,6 +60,14 @@ Tester = Struct.new(:client) do
|
|||
delegate :name, :to => :client, :prefix => false
|
||||
end
|
||||
|
||||
class ParameterSet
|
||||
delegate :[], :[]=, :to => :@params
|
||||
|
||||
def initialize
|
||||
@params = {:foo => "bar"}
|
||||
end
|
||||
end
|
||||
|
||||
class Name
|
||||
delegate :upcase, :to => :@full_name
|
||||
|
||||
|
@ -83,6 +91,17 @@ class ModuleTest < ActiveSupport::TestCase
|
|||
assert_equal "Fred", @david.place.name
|
||||
end
|
||||
|
||||
def test_delegation_to_index_get_method
|
||||
@params = ParameterSet.new
|
||||
assert_equal "bar", @params[:foo]
|
||||
end
|
||||
|
||||
def test_delegation_to_index_set_method
|
||||
@params = ParameterSet.new
|
||||
@params[:foo] = "baz"
|
||||
assert_equal "baz", @params[:foo]
|
||||
end
|
||||
|
||||
def test_delegation_down_hierarchy
|
||||
assert_equal "CHICAGO", @david.upcase
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue