I have a yaml file in the format:
parameters:
- param_name: age
requires:
- name
- param_name: height
requires:
- name
Based on this format I would like to accept a hash of keys and values and determine if the combination of keys and values is valid. For example based on the above example if someone submitted a hash with the values:
{'age' => 15, 'height' => '6ft'}
it would be considered invalid since the parameter name is required. So a valid submission would look like
{'age' => 15, 'height' => '6ft', 'name' => 'Abe Lincoln'}.
Essentially what I want is this:
For each parameter object, if it has a requires array underneath it. Check all parameter param_names for elements in that array, if any are missing exit.
I have a very ugly double loop that checks for this but I want to tighten the code up. I think I can use blocks in order to validate the data I need. Here is what I have come up with so far:
require 'yaml'
requirements = YAML.load_file('./require.yaml')
require_fields = Array.new
requirements['parameters'].each do |param|
require_fields.concat(param['require']) if param.has_key? 'require'
end
require_fields.each do |requirement|
found = false
requirements['parameters'].each do |param|
if param['param_name'] == requirement
found = true
end
end
abort "#{requirement} is a required field" unless found
end
You can clean this up a lot if you make it more idiomatic Ruby:
require 'yaml'
requirements = YAML.load_file('./require.yaml')
require_fields = requirements['parameters'].select do |param|
param.has_key?('require')
end.map do |param|
param['require']
end
require_fields.each do |requirement|
found = requirements['parameters'].any? do |param|
param['param_name'] == requirement
end
abort "#{requirement} is a required field" unless found
end
You could also do this:
require_fields = requirements['parameters'].map do |param|
param['require']
end.compact
Where that's probably good enough so long as your require
is either something or nil
.
You could also transform that input YAML into a simple hash structure of dependencies:
dependencies = requirements.map do ||
[ param['param_name'], param['requires'] ]
end.to_h
Then you can test really easily:
dependencies.each do |name, requirements|
found = requirements.find do |required_name|
!dependencies[required_name]
end
abort "#{found} is a required field" unless found
end
This is a really rough adaptation of your code, but I hope it gives you some ideas.