1. returning
returning String.new do |item|
item << user.first_name
item << user.second_name if user.second_name
item << user.family_name
end
看看这个方法的定义:
def returning(value)
yield(value)
value
end
2. delegate
>> Person = Struct.new(:name, :address)
=> Person
>> class Invoice < Struct.new(:client)
>> delegate :name, :address, :to => :client
>> end
=> [:name, :address]
>> john_doe = Person.new("John Doe", "Vimmersvej 13")
=> #<struct Person name="John Doe", address="Vimmersvej 13">
>> invoice = Invoice.new(john_doe)
=> #<struct Invoice client=#<struct Person name="John Doe", address="Vimmersvej 13">>
>> invoice.name
=> John Doe
>> invoice.address
=>Vimmersvej 13
实现:
class Module
# Delegate method
# It expects an array of arguments that contains
# the methods to be delegated and a hash of options
def delegate(*methods)
# Pop up the options hash from arguments array
options = methods.pop
# Check the availability of the options hash
# and more specifically the :to option
# Raises an error if one of them is not there
unless options.is_a?(Hash) && to = options[:to]
raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
end
# Make sure the :to option follows syntax rules
# for method names
if options[:prefix] == true && options[:to].to_s =~ /^[^a-z_]/
raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
end
# Set the real prefix value
prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_"
# Here comes the magic of ruby :)
# Reflection techniques are used here:
# module_eval is used to add new methods on the fly which:
# expose the contained methods' objects
methods.each do |method|
module_eval("def #{prefix}#{method}(*args, &block)\n#{to}.__send__(#{method.inspect}, *args, &block)\nend\n", "(__DELEGATION__)", 1)
end
end
end