Skip to content

Instantly share code, notes, and snippets.

@nwjsmith
Created March 29, 2012 20:10
Show Gist options
  • Save nwjsmith/2243186 to your computer and use it in GitHub Desktop.
Save nwjsmith/2243186 to your computer and use it in GitHub Desktop.
Compare the 'schema' of two hashes
Hash#structurally_equal?
when compared with a single-level hash
with the same keys
should be true
with different keys
should be false
with more keys
should be false
with less keys
should be false
when compared with a multi-level hash
with the same keys at all levels
should be true
with different keys at a lower level
should be false
Finished in 0.00143 seconds
6 examples, 0 failures
require 'rspec'
require 'set'
class Hash
def structurally_equal?(other)
return false unless Set.new(keys) == Set.new(other.keys)
nested = values.select { |v| v.respond_to? :keys }
other_nested = other.values.select { |v| v.respond_to? :keys }
nested.zip(other_nested).all? { |(n, o)| n.structurally_equal? o }
end
end
describe Hash, '#structurally_equal?' do
IRRELEVANT = :chunky_bacon
subject { object.structurally_equal?(other) }
context 'when compared with a single-level hash' do
context 'with the same keys' do
let(:object) { { a: IRRELEVANT, b: IRRELEVANT } }
let(:other) { { a: IRRELEVANT, b: IRRELEVANT } }
it { should be_true }
end
context 'with different keys' do
let(:object) { { a: IRRELEVANT, b: IRRELEVANT } }
let(:other) { { a: IRRELEVANT, c: IRRELEVANT } }
it { should be_false }
end
context 'with more keys' do
let(:object) { { a: IRRELEVANT } }
let(:other) { { a: IRRELEVANT, c: IRRELEVANT } }
it { should be_false }
end
context 'with less keys' do
let(:object) { { a: IRRELEVANT, b: IRRELEVANT } }
let(:other) { { a: IRRELEVANT } }
it { should be_false }
end
end
context 'when compared with a multi-level hash' do
context 'with the same keys at all levels' do
let(:object) { { a: { b: { c: IRRELEVANT } } } }
let(:other) { { a: { b: { c: IRRELEVANT } } } }
it { should be_true }
end
context 'with different keys at a lower level' do
let(:object) { { a: { b: { c: IRRELEVANT } } } }
let(:other) { { a: { b: { d: IRRELEVANT } } } }
it { should be_false }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment