Module
The Forwardable module provides delegation of specified methods to a designated object, using the methods def_delegator and def_delegators.
For example, say you have a class RecordCollection which contains an array @records. You could provide the lookup method record_number(), which simply calls [] on the @records array, like this:
require 'forwardable' class RecordCollection attr_accessor :records extend Forwardable def_delegator :@records, :[], :record_number end
We can use the lookup method like so:
r = RecordCollection.new r.records = [4,5,6] r.record_number(0)
Further, if you wish to provide the methods size, <<, and map, all of which delegate to @records, this is how you can do it:
class RecordCollection def_delegators :@records, :size, :<<, :map end r = RecordCollection.new r.records = [1,2,3] r.record_number(0) r.size r << 4 r.map { |x| x * 2 }
You can even extend regular objects with Forwardable.
my_hash = Hash.new my_hash.extend Forwardable my_hash.def_delegator "STDOUT", "puts" my_hash.puts "Howdy!"
Another example
You could use Forwardable as an alternative to inheritance, when you don’t want to inherit all methods from the superclass. For instance, here is how you might add a range of Array instance methods to a new class Queue:
class Queue extend Forwardable def initialize @q = [ ] end def_delegator :@q, :push, :enq def_delegator :@q, :shift, :deq def_delegators :@q, :clear, :first, :push, :shift, :size end q = Thread::Queue.new q.enq 1, 2, 3, 4, 5 q.push 6 q.shift while q.size > 0 puts q.deq end q.enq "Ruby", "Perl", "Python" puts q.first q.clear puts q.first
This should output:
2 3 4 5 6 Ruby nil
Notes
Be advised, RDoc will not detect delegated methods.
forwardable.rb provides single-method delegation via the def_delegator and def_delegators methods. For full-class delegation via DelegateClass, see delegate.rb.
Constants
Version for backward compatibility
Attributes
ignored
Instance Methods
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 q.push 23 q.to_i
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
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.