Archive for the ‘reflection’ Category
Variable/optional parameter methods, symbols and ruby
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.