views:

244

answers:

2

I'm pretty sure I saw on a Rails related site something along the lines of:

def my_function(*opts)
  opts.require_keys(:first, :second, :third)
end

And if one of the keys in require_keys weren't specified, or if there were keys that weren't specified, an exception was raised. I've been looking through ActiveSupport and I guess I might be looking for something like the inverse of except.

I like to try and use as much of the framework as possible compared to writing my own code, that's the reason I'm asking when I know how to make the same functionality on my own. :)

At the moment I'm doing it through the normal merge routine and making sure that I have what I need with some IFs.

A: 

I think the method you're thinking of is assert_valid_keys (documentation here) but this only raises an exception if any unexpected keys exist in the hash, not if any of the specified keys are missing. i.e. if a hash is being used to pass options to a method it can be used to check for invalid options not for required options.

mikej
Thanks, this was what I was thinking about. :)
ba
A: 

You can do this yourself relatively easily. As was stated in an earlier answer, half your work is done for you in assert_valid_keys. You can roll your own method to do the rest.

def my_function( *opts )
  opts.require_and_assert_keys( :first, :second, :third )
end

create lib/hash_extensions.rb with the following:

class Hash
  def require_and_assert_keys( *required_keys )
    assert_valid_keys( keys )
    missing_keys = required_keys.inject(missing=[]) do |missing, key|
      has_key?( key ) ? missing : missing.push( key )
    end
    raise( ArgumentError, "Missing key(s): #{missing_keys.join( ", ")}" ) unless missing_keys.empty?
  end
end

finally, in config/environment.rb, add this to make it work:

require 'hash_extensions'
irkenInvader