I suggest you use the hash (but keep reading for other alternatives).
Why?
Allowing arbitrary named arguments makes for extremely unstable code.
Let's say you have a method foo
that you want to accept these theoretical named arguments.
Scenarios:
The called method (foo
) needs to call a private method (let's call it bar
) that takes no arguments. If you pass an argument to foo
that you wanted to be stored in local variable bar
, it will mask the bar
method. The workaround is to have explicit parentheses when calling bar
.
Let's say foo
's code assigns a local variable. But then the caller decides to pass in an arg with the same name as that local variable. The assign will clobber the argument.
Basically, a method's caller must never be able to alter the logic of the method.
Alternatives
An alternate middle ground involves OpenStruct
. It's less typing than using a hash.
require 'ostruct'
os = OpenStruct.new(:a => 1, :b => 2)
os.a # => 1
os.a = 2 # settable
os.foo # => nil
Note that OpenStruct
allows you access non-existent members - it'll return nil
. If you want a stricter version, use Struct
instead.
This creates an anonymous class, then instantiates the class.
h = {:a=>1, :b=>2}
obj = Struct.new(* h.keys).new(* h.values)
obj.a # => 1
obj.a = 2 # settable
obj.foo # NoMethodError