instance method
delegate_missing_to
Ruby on Rails 7.1.6
Since v5.2.8.1Signature
delegate_missing_to(target, allow_nil: nil)
When building decorators, a common pattern may emerge:
class Partition
def initialize(event)
@event = event
end
def person
detail.person || creator
end
private
def respond_to_missing?(name, include_private = false)
@event.respond_to?(name, include_private)
end
def method_missing(method, *args, &block)
@event.send(method, *args, &block)
end
end
With Module#delegate_missing_to, the above is condensed to:
class Partition
delegate_missing_to :@event
def initialize(event)
@event = event
end
def person
detail.person || creator
end
end
The target can be anything callable within the object, e.g. instance variables, methods, constants, etc.
The delegated method must be public on the target, otherwise it will raise DelegationError. If you wish to instead return nil, use the :allow_nil option.
The marshal_dump and _dump methods are exempt from delegation due to possible interference when calling Marshal.dump(object), should the delegation target method of object add or remove instance variables.
Parameters
-
targetreq -
allow_nilkey = nil
Source
# File activesupport/lib/active_support/core_ext/module/delegation.rb, line 318
def delegate_missing_to(target, allow_nil: nil)
target = target.to_s
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target) || target == "__target"
if allow_nil
module_eval <<~RUBY, __FILE__, __LINE__ + 1
def respond_to_missing?(name, include_private = false)
# 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
def method_missing(method, *args, &block)
__target = #{target}
if __target.nil? && !nil.respond_to?(method)
nil
elsif __target.respond_to?(method)
__target.public_send(method, *args, &block)
else
super
end
end
ruby2_keywords(:method_missing)
RUBY
else
module_eval <<~RUBY, __FILE__, __LINE__ + 1
def respond_to_missing?(name, include_private = false)
# 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
def method_missing(method, *args, &block)
__target = #{target}
if __target.nil? && !nil.respond_to?(method)
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
elsif __target.respond_to?(method)
__target.public_send(method, *args, &block)
else
super
end
end
ruby2_keywords(:method_missing)
RUBY
end
end
Defined in activesupport/lib/active_support/core_ext/module/delegation.rb line 318
· View on GitHub
· Improve this page
· Find usages on GitHub
Defined in Module