Sugar for method accepting Hash of options
I had an API similar to the following:
Matcher.new(strict: true, async: true, only: [:a, :b, :c])
The #initalize
method was pretty standard:
def initalize(options = {})
@strict = options.fetch(:strict, false)
@async = options.fetch(:async, false)
@only = options.fetch(:only, [])
end
I could have used keyword arguments, such as:
def initialize(strict: false, async: false, only: [])
@strict, @async, @only = strict, async, only
end
But since there are many keys which can values of true
I thought it might be nice
to allow the user to do something like:
Matcher.new(:strict, :async, only: [:a, :b, :c])
So :strict
would be sugar for strict: true
.
Here is what I came up with:
def initialize(*args)
options = args.reduce({}) do |memo, item|
case item
when Symbol
memo[item] = true
when Hash
memo.merge!(item)
else
raise(ArgumentError, "Unsupported option: #{item.inspect} (#{item.class.name})")
end
memo
end
@strict = options.fetch(:strict, false)
@async = options.fetch(:async, false)
@only = options.fetch(:only, [])
end
I could have used each_with_object
instead of reduce
but I prefer,
descriptively, reduce
despite having to return memo
at the bottom of the
block, which is
not nessesary with each_with_object
.
Using each_with_object
is functionally equivalent to something like:
options = {}.tap do |memo|
args.each do |item|
case item
when Symbol
memo[item] = true
when Hash
memo.merge!(item)
else
raise(ArgumentError, "Unsupported option: #{item.inspect} (#{item.class.name})")
end
end
end
Any improvements please let me know.