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
|