1

Is there any spec expect which will compare two hashes by excluding specified keys alone.

H1 = {'name' => 'XXXXx', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}
H2 = {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}

Compare the above two hashes by excluding DOB key alone.

mechnicov
  • 12,025
  • 4
  • 33
  • 56

2 Answers2

2

I don't understand why do you need so, but you can use Hash#delete_if

RSpec.describe do
  let(:hash1) { {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'} }
  let(:hash2) { {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'} }

  it 'should correctly compare two subhashes' do
    expect(hash1.delete_if { |k,_| k == 'DOB' }).to eql(hash2.delete_if { |k,_| k == 'DOB' })
  end
end

If you want to make your expect more neatly you can convert hashes before.

Also you can use Hash#reject

RSpec.describe do
  it 'should correctly compare two subhashes' do
    hash1 = {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}
    hash2 = {'name' => 'XXXXX', 'age' => 29, 'DOB' => 'dd/mm/yyyy'}
    hash1, hash2 = [hash1, hash2].map { |h| h.reject { |k,_| k == 'DOB' } }

    expect(hash1).to eql(hash2)
  end
end
mechnicov
  • 12,025
  • 4
  • 33
  • 56
1

Rather than comparing two temporary hashes that equal H1 and H2 with the key 'DOB' (if present) removed, one could compare two temporary hashes that have keys 'DOB' with the same value. That value is arbitrary; I've used nil.

expect(H1.merge('DOB'=>nil).to eq(H2.merge('DOB'=>nil)))

Another way is:

expect((H1.keys|H2.keys).all? do |k| 
  k=='DOB' || (H1.key?(k) && H2.key?(k) && H1[k]==H2[k])
end.to eq(true)

H1.key?(k) && H2.key?(k) is there in case one of the hashes has a key k with value nil and the other hash does not have a key k.

This has the redeeming feature that it has a more modest memory requirement than do the two approaches I mentioned above.

Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100