mirror of https://github.com/rails/rails
`Module#delegate` avoid creating a unique fstring for each delegator
For example: ```ruby delegate :negative?, to: :value, as: Numeric ``` Before: ``` def negative?(&block) _ = @value _.negative?(&block) rescue NoMethodError => e if _.nil? && e.name == :negative? raise DelegationError, "ActiveSupport::Duration#negative? delegated to @value.negative?, but @value is nil: #{self.inspect}" else raise end end ``` After: ```ruby def negative?(&block) _ = @value _.negative?(&block) rescue NoMethodError => e if _.nil? && e.name == :negative? raise DelegationError.nil_target(:negative?, :"@value") else raise end end ``` Before almost every delegator would generate a large unique string that gets interned for the error message that is rarely if ever used. Rather than to "hardcode" a unique string, we now only pass pre-existing symbols to a method helper that will build the error message. This alone saves about 160B per delegator, and the method bytecode is also marginally smaller (but it's harder to assess how much this actually saves)
This commit is contained in:
parent
9dab3e4184
commit
4bded3c00a
|
@ -5,7 +5,13 @@ require "set"
|
|||
class Module
|
||||
# Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
|
||||
# option is not used.
|
||||
class DelegationError < NoMethodError; end
|
||||
class DelegationError < NoMethodError
|
||||
class << self
|
||||
def nil_target(method_name, target) # :nodoc:
|
||||
new("#{method_name} delegated to #{target}, but #{target} is nil")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RUBY_RESERVED_KEYWORDS = %w(__ENCODING__ __LINE__ __FILE__ alias and BEGIN begin break
|
||||
case class def defined? do else elsif END end ensure false for if in module next nil
|
||||
|
@ -266,7 +272,7 @@ class Module
|
|||
" _.#{method}(#{definition})" <<
|
||||
"rescue NoMethodError => e" <<
|
||||
" if _.nil? && e.name == :#{method}" <<
|
||||
%( raise DelegationError, "#{self}##{method_name} delegated to #{receiver}.#{method}, but #{receiver} is nil: \#{self.inspect}") <<
|
||||
" raise DelegationError.nil_target(:#{method_name}, :'#{receiver}')" <<
|
||||
" else" <<
|
||||
" raise" <<
|
||||
" end" <<
|
||||
|
@ -347,7 +353,7 @@ class Module
|
|||
if #{allow_nil == true}
|
||||
nil
|
||||
else
|
||||
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
|
||||
raise DelegationError.nil_target(method, :'#{target}')
|
||||
end
|
||||
else
|
||||
raise
|
||||
|
|
Loading…
Reference in New Issue