1

I have an options hash and a method to update it - but the options hash could change and if it does I want my tests to fail. What's a good way to write this?

raise RuntimeError, msg unless options.keys.include?(
  :external_uid,
  :display_name,
  :country_code
)

If options.keys doesn't include exactly those three items, an error should be raised.

solution that i almost used (thanks bjhaid):

def ensure_correct_options!(options)
  msg = "Only 'external_uid', 'display_name' and 'country_code' can be "
  msg += "updated. Given attributes: #{options.keys.inspect}"

  raise RuntimeError, msg unless options.keys == [
    :external_uid,
    :display_name,
    :country_code
  ]
end  
Community
  • 1
  • 1
dax
  • 10,779
  • 8
  • 51
  • 86
  • 3
    Maybe [this](http://stackoverflow.com/questions/8026300/check-for-multiple-items-in-array-using-include-ruby-beginner) answer could help. – Magnuss Apr 14 '14 at 12:27
  • @Magnuss, cheers, i saw that but i wanted exact matches only...i ended up going with a much simpler/face-slap-inducing solution. cheers – dax Apr 14 '14 at 12:58
  • @dax, your solution would fail, if the elements in the array are ordered in a different manner have a look at [Hash#fetch](http://www.ruby-doc.org/core-2.1.1/Hash.html#method-i-fetch) has a behavior close to what you want, but on single keys – bjhaid Apr 14 '14 at 13:01

2 Answers2

4

The options probably have a value, so I would write:

unless options[:external_uid] && options[:display_name] && options[:country_code]
  raise ArgumentError, ":external_uid, :display_name and :country_code required"
end

(I've replaced RuntimeError with ArgumentError because this seems to be about arguments)

Stefan
  • 109,145
  • 14
  • 143
  • 218
1

If there were more than three values to test for inclusion as keys in the hash, you might do it t like this:

unless ([:external_uid, :display_name,...] - options.keys).empty? \
  raise ArgumentError, ":external_uid, :display_Nam,... are required"
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100