Fellps
Fellps

Reputation: 415

Better way to validates a hash parameter in a method on Ruby?

Is there a better DRY way to validate a parameter hash that contains certain key like this?

module Exemple

 def foo_method(config)
  validate_config(config)

  foo = config[:foo]
  bar = config[:bar]
  qux = config[:qux] || {}

 end

 private

 def validate_config(config)
  raise(ArgumentError, "No foo config found", caller) unless config.has_key?(:foo)
  raise(ArgumentError, "No bar config found", caller) unless config.has_key?(:bar)
 end

end

Upvotes: 0

Views: 371

Answers (3)

Stefan
Stefan

Reputation: 114188

Use Hash#fetch:

def foo_method(config)
  foo = config.fetch(:foo)
  bar = config.fetch(:bar)
  qux = config.fetch(:qux, {})
end

foo_method({})               #=> key not found: :foo (KeyError)
foo_method({foo: 1})         #=> key not found: :bar (KeyError)
foo_method({foo: 1, bar: 2}) #=> no error

You can also pass a block to fetch that is called if they given key was not found, e.g.:

  foo = config.fetch(:foo) { raise ArgumentError, "No foo config found" }

Upvotes: 3

RickyTomatoes
RickyTomatoes

Reputation: 722

Store the required config keys as an array in a private method for the module, then subtract the passed config hash's keys from that, and see if the resulting array is empty, if not throw an error with the missing keys.

module Example
   def foo_method(config)
     validate_config!(config)
     #do stuff
   end

   private

   def validate_config!(config)
     missing_keys = [:foo, :bar] - config.keys
     raise ArgumentError, "Config missing required keys: #{missing_keys.join(', ')}", caller unless missing_keys.empty?
   end

end

That way, if you need to require more keys you can just add them to the array, and the resulting errors will always contain all the missing keys instead of just the first one encountered.

Upvotes: 1

maniacalrobot
maniacalrobot

Reputation: 2463

Depending on your version of ruby, you could use keyword arguments? http://ruby-doc.org/core-2.1.0/doc/syntax/methods_rdoc.html#label-Keyword+Arguments

Or, scale your current solution by looping over the required keys?

%i{foo bar}.each do |k|
    raise(ArgumentError, "No #{k} config found", caller) unless config.has_key?(k)
end

Upvotes: 1

Related Questions