Patches item #1923, was opened at 2005-05-17 07:50
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=1700&aid=1923&group_id=426

>Category: Developer Tools/Libs
Group: v1.8.x
Status: Open
Resolution: None
Priority: 3
Submitted By: Daniel Berger (djberg96)
Assigned to: Nobody (None)
Summary: Forwardable, reworked

Initial Comment:
The following code is a reworked version of the current Forwardable module.  It eliminates SingleForwardable altogther and adds the "delegate" method, at the suggestion of Florian Gross.

I didn't provide a unified diff because I wasn't sure what additional documentation folks would want to include at the top of the file (and because there are so many code and doc changes).

Attached is a corresponding test suite that should probably go under test/forwardable (which would need to be created).

Regards,

Dan

# forwardable.rb
#
# == Synopsis
# Provides a mechanism to allow classes to delegate named method calls
# to other objects.
#
# == Usage
#    class Foo
#       extend Forwardable
#       delegate :length => :@str
#       delegate [:first, :last] => :@arr
#       def initialize
#          @arr = ["foo","bar","baz"]
#          @str = "hello"
#       end
#    end
#
#    f = Foo.new
#    puts f.length # 5, length of @str
#    puts f.first  # "foo", first element of @arr
#    puts f.last   # "baz", last element of @arr
#
# == Author
# Keiju Ishitsuka
#
# Revised by: Daniel J. Berger with suggestions from Florian Gross.
#
module Forwardable
   FORWARDABLE_VERSION = "1.0.0"

   # 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 accessor to which the methods will be delegated.
   #
   # :call-seq:
   #    delegate method => accessor
   #    delegate [method, method, ...] => accessor
   #
   def delegate(hash)
      hash.each{ |methods, accessor|
         methods = methods.to_s unless methods.respond_to?(:each)
         methods.each{ |method|
            def_instance_delegator(accessor, method)
         }
      }
   end

   # Delegates +methods+ to the given +accessor+.
   #
   # :call-seq:
   #     def_delegators(accessor, *methods)
   #
   def def_instance_delegators(accessor, *methods)
      methods.delete("__send__")
      methods.delete("__id__")
      methods.each{ |method|
         def_instance_delegator(accessor, method)
      }
   end

   # Delegates a single +method+ to the given +accessor+.
   #
   # :call-seq:
   #     def_delegator(accessor, method, alias=nil)
   #
   # If an alias is provided, the accessor will respond to that alias instead
   # of the original method.
   def def_instance_delegator(accessor, method, ali = method)
      str = %Q{
         def #{ali}(*args, &block)
            #{accessor}.send(:#{method}, *args, &block)
         end
      }

      # If it's not a class or module, it's an instance
      begin
         module_eval(str)
      rescue
         instance_eval(str)
      end
  end

  alias def_delegators def_instance_delegators
  alias def_delegator def_instance_delegator
end


----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=1700&aid=1923&group_id=426