#!/usr/bin/env ruby class Hash def node_lineages reduce_to_node = Proc.new do |prefix_key,value| if value.is_a?(Hash) value.map do |child_key,child_value| new_prefix = [prefix_key,child_key].join('.') reduce_to_node.call(new_prefix,child_value) end elsif value.is_a?(Array) value.map do |child_item| new_prefix = "#{prefix_key}[]" reduce_to_node.call(new_prefix, child_item) end else [prefix_key, value].join('=') end end self.map do |key, value| reduce_to_node.call(key, value) end end end hash = { a: :b } expected = 'a=b' actual = hash.node_lineages raise "Test failed : #{expected.inspect} expected, #{actual.inspect} actual" unless actual == expected hash = { a: { b: :c, d: :e } } expected = "a.b=c ; a.d=e" actual = hash.node_lineages.join(';') raise "Test failed : #{expected.inspect} expected, #{actual.inspect} actual" unless actual == expected hash = { a: { b: :c, d: :e }, f: [ :g, :h, :i ] } expected = <<-HEREDOC a.b=c a.d=e f[]=g f[]=h f[]=i HEREDOC actual = hash.node_lineages.join("\n") raise "Test failed : #{expected.inspect} expected, #{actual.inspect} actual" unless actual == expected puts 'All tests OK :)'