This page contains automated test results for code from O'Reilly's Ruby Cookbook. If this code looks interesting or useful, you might want to buy the whole book.

Simulating Keyword Arguments
CodeExpectedActual
def fun_with_text(text, args={})
  text = text.upcase if args[:upcase]
  text = text.downcase if args[:downcase]
  if args[:find] and args[:replace]
    text = text.gsub(args[:find], args[:replace]) 
  end
  text = text.slice(0, args[:truncate_at]) if args[:truncate_at]
  return text
end
fun_with_text("Foobar", {:upcase => true, :truncate_at => 5})
"FOOBA" "FOOBA"
fun_with_text("Foobar", :upcase => true, :truncate_at => 5)
"FOOBA" "FOOBA"
fun_with_text("Foobar", :find => /(o+)/, :replace => '\1d', :downcase => true)
"foodbar" "foodbar"
###
This mix-in module lets methods match a caller's hash of keyword
parameters against a hash the method keeps, mapping keyword
arguments to default parameter values.
Error! (Exception?) Here's stdout:
#
If the caller leaves out a keyword parameter whose default value is
:MANDATORY (a constant in this module), then an error is raised.
Error! (Exception?) Here's stdout:
#
If the caller provides keyword parameters which have no
corresponding keyword arguments, an error is raised.
Error! (Exception?) Here's stdout:
#
module KeywordProcessor
  MANDATORY = :MANDATORY
  def process_params(params, defaults)
    # Reject params not present in defaults.
    params.keys.each do |key|
      unless defaults.has_key? key
        raise ArgumentError, "No such keyword argument: #{key}"
      end
    end
    result = defaults.dup.update(params)
    # Ensure mandatory params are given.
    unfilled = result.select { |k,v| v == MANDATORY }.map { |k,v| k.inspect }
    unless unfilled.empty?
      msg = "Mandatory keyword parameter(s) not given: #{unfilled.join(', ')}"
      raise ArgumentError, msg
    end
    return result
  end
end
class TextCanvas
  include KeywordProcessor
  def render(text, args={})
    args = process_params(args, {:font => 'New Reykjavik Solemn', :size => 36, 
                                 :bold => false, :x => :MANDATORY, 
                                 :y => :MANDATORY }.freeze)
    # ...    
    puts "DEBUG: Found font #{args[:font]} in catalog."
    # ...
  end
end
canvas = TextCanvas.new
canvas.render('Hello', :x => 4, :y => 100)
DEBUG: Found font New Reykjavik Solemn in catalog.
DEBUG: Found font New Reykjavik Solemn in catalog.
canvas.render('Hello', :x => 4, :y => 100, :font => 'Lacherlich')
DEBUG: Found font Lacherlich in catalog.
DEBUG: Found font Lacherlich in catalog.
canvas.render('Hello', :font => "Lacherlich")
ArgumentError: Mandatory keyword parameter(s) not given: :x, :y
...
ArgumentError: Mandatory keyword parameter(s) not given: :x, :y
	from (irb):31:in `process_params'
	from (irb):39:in `render'
	from (irb):50
canvas.render('Hello', :x => 4, :y => 100, :italic => true)
ArgumentError: No such keyword argument: italic
...
ArgumentError: No such keyword argument: italic
	from (irb):23:in `process_params'
	from (irb):21:in `process_params'
	from (irb):39:in `render'
	from (irb):51