Module: ClosureForwardable

Defined in:
lib/closure_forwardable.rb,
lib/closure_forwardable/version.rb

Overview

The ClosureForwardable module provides delegation of specified methods to a designated object, using the methods #delegate, #def_delegator, and #def_delegators.

This module is intended to be used very similar to the Forwardable module in the Ruby standard library. For basic usage guidelines, see there. Generally, you should use the simple Forwardable module if possible as method calls will be slightly faster while providing the same functionality.

Use ClosureForwardable if you need to forward methods to a receiver that is not available by the including module itself. Using ClosureForwardable, you can forward methods to arbitrary objects.

Defined Under Namespace

Modules: Version

Constant Summary collapse

FILE_REGEXP =

A regular expression matching the current file so that we can filter backtraces

Regexp.new(Regexp.escape(__FILE__))
VERSION =

The ClosureForwardable version as a semver-compliant string

Version::STRING

Class Attribute Summary collapse

Instance Method Summary collapse

Class Attribute Details

.debugBoolean

If true, __FILE__ will remain in the backtrace in the event an exception is raised.

Returns:

  • (Boolean)


28
29
30
# File 'lib/closure_forwardable.rb', line 28

def debug
  @debug
end

Instance Method Details

#closure_delegate(hash) ⇒ void Also known as: delegate

This method returns an undefined value.

Takes a hash as its argument. The key is a symbol or an array of symbols. These symbols correspond to method names. The value is the receiver to which the methods will be delegated.

Parameters:

  • hash (Hash<Symbol,String,Array<Symbol, String> => Object>)


37
38
39
40
41
42
43
44
# File 'lib/closure_forwardable.rb', line 37

def closure_delegate(hash)
  hash.each do |methods, receiver|
    methods = [methods] unless methods.respond_to?(:each)
    methods.each do |method|
      def_closure_delegator(receiver, method)
    end
  end
end

#def_closure_delegator(receiver, method, method_alias = method) ⇒ void Also known as: def_delegator

This method returns an undefined value.

Define method as delegator instance method with an optional alias name ali. Method calls to ali will be delegated to receiver.method.

Examples:

class MyQueue
  extend InheritedSettings::ClosureForwardable

  attr_reader :internal
  def initialize
    @internal = []
  end
end

external = []
MyQueue.def_delegator external, :push, :<<
queue = MyQueue.new

queue << 42
external              #=> [42]

queue.internal << 23
queue.internal        #=> [23]
external              #=> [42]

Parameters:

  • receiver (Object)

    the object which will be the receiver of all delegated methods calls

  • method (Symbol, String)

    the name of the method on the receiver

  • method_alias (Symbol, String) (defaults to: method)

    The method name created in the current module, by default, we use the same name as the method name on the receiver



101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/closure_forwardable.rb', line 101

def def_closure_delegator(receiver, method, method_alias = method)
  define_method(method_alias) do |*args, &block|
    begin
      receiver.__send__(method, *args, &block)
    rescue Exception
      unless ::ClosureForwardable.debug
        $ERROR_POSITION.delete_if do |error_line|
          ::ClosureForwardable::FILE_REGEXP =~ error_line
        end
      end
      ::Kernel.raise
    end
  end
end

#def_closure_delegators(receiver, *methods) ⇒ void Also known as: def_delegators

This method returns an undefined value.

Shortcut for defining multiple delegator methods, but with no provision for using a different name.

Examples:

# This definition
def_delegators records, :size, :<<, :map

# is exactly the same as this:
def_delegator records, :size
def_delegator records, :<<
def_delegator records, :map

Parameters:

  • receiver (Object)

    the object which will be the receiver of all delegated methods calls

  • methods (Array<Symbol, String>)

    Any number of methods to delegate



62
63
64
65
66
67
68
# File 'lib/closure_forwardable.rb', line 62

def def_closure_delegators(receiver, *methods)
  excluded_methods = ['__send__'.freeze, '__id__'.freeze]
  methods.each do |method|
    next if excluded_methods.include?(method.to_s)
    def_closure_delegator(receiver, method)
  end
end