diff options
Diffstat (limited to 'activesupport/lib/active_support/core_ext/module')
-rw-r--r-- | activesupport/lib/active_support/core_ext/module/delegation.rb | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 9fe7f8fe01..14d7f0c484 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -205,18 +205,18 @@ class Module if allow_nil method_def = [ "def #{method_prefix}#{method}(#{definition})", - "_ = #{to}", - "if !_.nil? || nil.respond_to?(:#{method})", - " _.#{method}(#{definition})", - "end", - "end" + " _ = #{to}", + " if !_.nil? || nil.respond_to?(:#{method})", + " _.#{method}(#{definition})", + " end", + "end" ].join ";" else exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") method_def = [ "def #{method_prefix}#{method}(#{definition})", - " _ = #{to}", + " _ = #{to}", " _.#{method}(#{definition})", "rescue NoMethodError => e", " if _.nil? && e.name == :#{method}", @@ -274,8 +274,14 @@ class Module # variables, methods, constants, etc. # # The delegated method must be public on the target, otherwise it will - # raise +NoMethodError+. - def delegate_missing_to(target) + # raise +DelegationError+. If you wish to instead return +nil+, + # use the <tt>:allow_nil</tt> option. + # + # The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from + # delegation due to possible interference when calling + # <tt>Marshal.dump(object)</tt>, should the delegation target method + # of <tt>object</tt> add or remove instance variables. + def delegate_missing_to(target, allow_nil: nil) target = target.to_s target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target) @@ -284,6 +290,7 @@ class Module # It may look like an oversight, but we deliberately do not pass # +include_private+, because they do not get delegated. + return false if name == :marshal_dump || name == :_dump #{target}.respond_to?(name) || super end @@ -295,7 +302,11 @@ class Module super rescue NoMethodError if #{target}.nil? - raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil" + if #{allow_nil == true} + nil + else + raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil" + end else raise end |