First if you want only for optional parameter in a method, just see the next two examples :
def foo(bar=:hello)
puts bar
end
foo #=> hello
foo bye #=> bye
The second example :
def add_book(title=>"no title")
arg={:, :author=>"anonymous", :language=>"esperanto"}
arg.merge! p_argirb(main):020:1>
end
add_book :title=>"El Qujote", :author=>"Miguel De Cervantes", :language=>"spanish"
=> {:language=>"spanish", :title=>"El Qujote", :author=>"Miguel De Cervantes"}
add_book :title=>"El Qujote", :author=>"Miguel De Cervantes"
=> {:language=>"esperanto", :title=>"El Qujote", :author=>"Miguel De Cervantes"}
add_book :title=>"El Qujote", :author=>"Miguel De Cervantes" :foo=>:Bar
=> {:language=>"esperanto", :title=>"El Qujote", :author=>"Miguel De Cervantes"}
Sometimes is usefull to have an optional/variable parameters method, . In a recent domain specific languages (DSL) design i have to implement a object that have some optional parameters.
For example we want to add a book to our database, But we don’t want to write every single attribute, is the attribute is not present then is initialize with a default value. The properties are
add_book :title=>"El quijote", :author=> "Miguel de Cervantes"
add_book :title=>"El quijote", :author=> "Miguel de Cervantes", :tag=>"novel"
add_book :title=>"El quijote"
add_book :title=>"hogehoge", :language=>"Japanese" # => raise ArgumentError
Asking in the ruby list, Hidetoshi NAGAI, teach me how to use symbols, variable parameter methods (varargs), to create this clean example. The main idea is use a hash for parameter value preinitializate and check is the parameter is in the list. BTW, he also override the method_missing method to emulate all the getters and setters for the object.
class Book
def initialize(properties = {})
@props = {
'title' => '',
'author' => '',
'tag' => nil,
'price' => nil,
'ISBN' => nil,
}
properties.each{|k, v|
k = k.to_s
raise ArgumentError, "unknown property: #{k}" unless @props.key?(k)
@props[k] = v
}
end
def method_missing(id, *args)
prop = id.id2name
case args.length
when 1
if prop[-1] == ?= # it will be a setter
self[prop[0..-2]] = args[0]
args[0]
else # Else it will be "self.property(val)".
# Then call "self[] = val"
self[prop] = args[0]
self
end
when 0 # the getter
self[prop]
else #continue the search
super(id, *args)
end
end
def [](prop)
prop = prop.to_s
raise ArgumentError, "unknown property: #{prop}" unless @props.key?(prop)
@props[prop]
end
def []=(prop, val)
prop = prop.to_s
raise ArgumentError, "unknown property: #{prop}" unless @props.key?(prop)
@props[prop] = val
end
end
def add_book(props)
book = Book.new(props)
puts "case1: title : #{book.title} -- Author : #{book.author}"
puts "case2: title : #{book[:title]} -- Author : #{book[:author]}"
puts "case3: title : #{book['title']} -- Author : #{book['author']}"
book
end
In a next post i explain ho to to improve the optinal parameter using meta-programming.