> So if a.eql?(b), then a.hash MUST EQUAL b.hash.

Only if the object implementation (in case, Hash) agreeds on the
general contract for objects that try to be useful as hash keys.

> irb(main):040:0> a.eql?(b)
> => true

When I do this, I get:

irb(main):003:0> {1=>2}.eql?({1=>2})
=> false


For numbers, strings and arrays you will find .hash and .eql? methods
which are consistent, meaning they play fair as hash keys.

This is not the same with Hash objects. Probably for performance
reasons and because in some ocasions one expects hashes to be equal
only if they are the same objects, .hash and .eql? are not defined
such that hashes are equal if they have the same pairs. I think they
actually inherit Object methods such that
     hash1.eql?(hash2)    is the same as    hash1===hash2
and
     hash1.hash      calls     Object.hash    which is based on object ID

But you can do that. Try:

class Hash
  def hash
    return self.to_a.hash
  end

  def eql?(b)
    return self.to_a.eql?(b.to_a)
  end
end


a={1=>2} 
b={1=>2}
c={}
c[a]=1 
c[b]=1 
c.inspect