Module: Aspera::Yaml
- Defined in:
- lib/aspera/yaml.rb
Class Method Summary collapse
-
.find_duplicate_keys(node, parent_path = nil, duplicate_keys = nil) ⇒ Array<String>
List of duplicate keys with their paths and occurrences.
-
.safe_load(yaml) ⇒ Object
Safely load YAML content raising an error if duplicate keys are found Validates the yaml, and then call ‘YAML.safe_load`.
Class Method Details
.find_duplicate_keys(node, parent_path = nil, duplicate_keys = nil) ⇒ Array<String>
Returns List of duplicate keys with their paths and occurrences.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/aspera/yaml.rb', line 11 def find_duplicate_keys(node, parent_path = nil, duplicate_keys = nil) duplicate_keys ||= [] parent_path ||= [] return duplicate_keys unless node.respond_to?(:children) if node.is_a?(Psych::Nodes::Mapping) counts = Hash.new(0) key_nodes = Hash.new{ |h, k| h[k] = []} node.children.each_slice(2) do |key_node, value_node| if key_node&.value counts[key_node.value] += 1 key_nodes[key_node.value] << key_node find_duplicate_keys(value_node, parent_path + [key_node.value], duplicate_keys) end end counts.each do |key_str, count| next if count <= 1 path = (parent_path + [key_str]).join('.') occurrences = key_nodes[key_str].map{ |kn| kn.start_line ? kn.start_line + 1 : 'unknown'}.join(', ') duplicate_keys << "#{path}: #{occurrences}" end else node.children.to_a.each{ |child| find_duplicate_keys(child, parent_path, duplicate_keys)} end duplicate_keys end |
.safe_load(yaml) ⇒ Object
Safely load YAML content raising an error if duplicate keys are found Validates the yaml, and then call ‘YAML.safe_load`
43 44 45 46 47 |
# File 'lib/aspera/yaml.rb', line 43 def safe_load(yaml) duplicate_keys = find_duplicate_keys(Psych.parse_stream(yaml)) raise "Duplicate keys: #{duplicate_keys.join('; ')}" unless duplicate_keys.empty? YAML.safe_load(yaml, permitted_classes: [Time, Date, Symbol]) end |