A question came up on the Ruby mailing list today about how one might pass
boolean flags in an option hash to a Ruby method, without having to explicitly
declare them as true
. To clarify, here’s the original question from Woody
Peterson:
I have a unix-inspired desire to pass arguments to a method where some are toggle flags and some are values, aka
"bash$ method --flag --config=/etc/method"
. I can think of a few ways to do it that are close, but if I had a hash that initiated value-less keys to true, I would have it.Example:
method(:flag, :another, :config => "/etc/whatever")
For some of the functionality I colud use
*args
and checkargs.include?(:foo)
, but then I couldn’t pass in key-value pairs easily.
I came up with a solution that I thought might prove useful, so I’m posting it
here. Essentially we add a method to convert any Enumerable
object to a
Hash
. The method builds a new hash by looping over the object; if the item is
a hash it is merged into the result, otherwise it is used as a key to which a
value is assigned (true
by default). Here goes:
module Enumerable
def to_hash(value = true)
inject({}) do |hash, item|
item.is_a?(Hash) ?
hash.update(item) :
hash[item] = value
hash
end
end
end
You can then convert a splat-args style argument to a hash easily:
def my_method(foo, bar, *args)
options = args.to_hash
if options[:flag] #...
end
# Call using explicit or implicit booleans
my_method('one', 'two', :flag => true, :val => 94)
my_method('one', 'two', :flag, :val => 94)
Note that the boolean flags must be given first if you want to omit the curly braces on the option hash; Ruby does not allow further non-hash arguments after you begin a braceless hash.