Module: Forwardable

Defined in:
lib/forwardable.rb,
lib/forwardable/impl.rb

Overview

:stopdoc:

Constant Summary collapse

VERSION =

Version of forwardable.rb

"1.3.2"
FORWARDABLE_VERSION =
VERSION

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.debugObject

ignored



121
122
123
# File 'lib/forwardable.rb', line 121

def debug
  @debug
end

Class Method Details

._compile_method(src, file, line) ⇒ Object



13
14
15
# File 'lib/forwardable/impl.rb', line 13

def self._compile_method(src, file, line)
  eval(src, nil, file, line)
end

._delegator_method(obj, accessor, method, ali) ⇒ Object

:nodoc:



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/forwardable.rb', line 201

def self._delegator_method(obj, accessor, method, ali)
  accessor = accessor.to_s unless Symbol === accessor

  if Module === obj ?
       obj.method_defined?(accessor) || obj.private_method_defined?(accessor) :
       obj.respond_to?(accessor, true)
    accessor = "#{accessor}()"
  end

  method_call = ".__send__(:#{method}, *args, &block)"
  if _valid_method?(method)
    loc, = caller_locations(2,1)
    pre = "_ ="
    mesg = "#{Module === obj ? obj : obj.class}\##{ali} at #{loc.path}:#{loc.lineno} forwarding to private method "
    method_call = "#{<<-"begin;"}\n#{<<-"end;".chomp}"
        unless defined? _.#{method}
          ::Kernel.warn #{mesg.dump}"\#{_.class}"'##{method}', uplevel: 1
          _#{method_call}
        else
          _.#{method}(*args, &block)
        end
      end;
  end

  _compile_method("#{<<-"begin;"}\n#{<<-"end;"}", __FILE__, __LINE__+1)
    proc do
      def #{ali}(*args, &block)
        #{pre}
        begin
          #{accessor}
        end#{method_call}
      end
    end
  end;
end

._valid_method?(method) ⇒ Boolean

Returns:

  • (Boolean)


3
4
5
6
7
8
9
10
11
# File 'lib/forwardable/impl.rb', line 3

def self._valid_method?(method)
  catch {|tag|
    eval("BEGIN{throw tag}; ().#{method}", binding, __FILE__, __LINE__)
  }
rescue SyntaxError
  false
else
  true
end

Instance Method Details

#def_instance_delegator(accessor, method, ali = method) ⇒ Object Also known as: def_delegator

Define method as delegator instance method with an optional alias name ali. Method calls to ali will be delegated to accessor.method. accessor should be a method name, instance variable name, or constant name. Use the full path to the constant if providing the constant name. Returns the name of the method defined.

class MyQueue
  CONST = 1
  extend Forwardable
  attr_reader :queue
  def initialize
    @queue = []
  end

  def_delegator :@queue, :push, :mypush
  def_delegator 'MyQueue::CONST', :to_i
end

q = MyQueue.new
q.mypush 42
q.queue    #=> [42]
q.push 23  #=> NoMethodError
q.to_i     #=> 1


186
187
188
189
190
191
192
193
194
# File 'lib/forwardable.rb', line 186

def def_instance_delegator(accessor, method, ali = method)
  gen = Forwardable._delegator_method(self, accessor, method, ali)

  # If it's not a class or module, it's an instance
  mod = Module === self ? self : singleton_class
  ret = mod.module_eval(&gen)
  mod.__send__(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7'
  ret
end

#def_instance_delegators(accessor, *methods) ⇒ Object Also known as: def_delegators

Shortcut for defining multiple delegator methods, but with no provision for using a different name. The following two code samples have the same effect:

def_delegators :@records, :size, :<<, :map

def_delegator :@records, :size
def_delegator :@records, :<<
def_delegator :@records, :map


154
155
156
157
158
159
# File 'lib/forwardable.rb', line 154

def def_instance_delegators(accessor, *methods)
  methods.each do |method|
    next if /\A__(?:send|id)__\z/ =~ method
    def_instance_delegator(accessor, method)
  end
end

#instance_delegate(hash) ⇒ Object Also known as: delegate

Takes a hash as its argument. The key is a symbol or an array of symbols. These symbols correspond to method names, instance variable names, or constant names (see def_delegator). The value is the accessor to which the methods will be delegated.

:call-seq:

delegate method => accessor
delegate [method, method, ...] => accessor


133
134
135
136
137
138
139
140
141
# File 'lib/forwardable.rb', line 133

def instance_delegate(hash)
  hash.each do |methods, accessor|
    unless defined?(methods.each)
      def_instance_delegator(accessor, methods)
    else
      methods.each {|method| def_instance_delegator(accessor, method)}
    end
  end
end