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.