require 'minitest/spec' require 'minitest/autorun' require 'set' class Schemas def initialize @schemas = Set.new end def <<(hash) @schemas << hash end def to_a @schemas.to_a end end class HashSchema def schema(hash) {}.tap do |result| hash.keys.sort.each do |key| result[key] = classify(hash, key) end end end private def classify(hash, key) case hash[key] when Hash schema(hash[key]) else hash[key].class.name.downcase end end end describe HashSchema do subject { HashSchema.new } describe 'when given unsorted hash keys' do let(:hash) { {'z' => 42, 'y' => 43, 'x' => '44'} } let(:expected) { {'x' => 'string', 'y' => 'fixnum', 'z' => 'fixnum'} } it 'sorts and classifies value types' do subject.schema(hash).must_equal expected end end describe 'when given unsorted nested hashes' do let(:hash) { {'z' => 42, 'y' => {'c' => true, 'b' => 12.1}} } let(:expected) { {'y' => {'b' => 'float', 'c' => 'trueclass'}, 'z' => 'fixnum'} } it 'recursively sorts and classifies value types' do subject.schema(hash).must_equal expected end end end describe Schemas do subject { Schemas.new } describe 'when given duplicate hashes' do let(:expected) { [{'a' => 42}, {'b' => 12}] } it 'only tracks distinct entries' do subject << {'a' => 42} subject << {'b' => 12} subject << {'a' => 42} subject.to_a.size.must_equal 2 subject.to_a.must_equal expected end end end