Reputation: 415
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
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
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
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