zapico
zapico

Reputation: 2396

Different hashes for the same object values in ruby

I have a problem with "hash" method from ruby: http://apidock.com/ruby/v1_8_7_330/Hash/hash

I use this to compare two different objects with the same content to find collisions between data base objects and new elements with the same attributes.

It has been apparently working for a long time (more than one year) but it has suddenly stopped working in my dev computer.

If I try this in the rails console:

a = {:a => 'a', :b=>'b'}
b = {:a => 'a', :b=>'b'}
a.hash
b.hash

I get the same value for both a.hash and b.hash (-3820017043059270405) in the same console. The problem is, if I change to another console it returns a different value from the first console (-1865824882785682267).

Shouldn't it be returning the same hash ever?

Thanks in advance.

Edit: It worked good in production because of ree 1.8.7 version.

Upvotes: 8

Views: 1415

Answers (2)

Neil Slater
Neil Slater

Reputation: 27207

From: http://ruby-doc.org/core-2.0/Object.html#method-i-hash

The hash value for an object may not be identical across invocations or implementations of ruby. If you need a stable identifier across ruby invocations and implementations you will need to generate one with a custom method.

Although this is documentation from Ruby 2.0, I believe this has been the case for a while - i.e. you are not guaranteed in general that Ruby objects that are equivalent using .eql? will have the same hash value computed in different Ruby processes.

When you call Hash.hash, my understanding is that this returns a combination of hash values calculated from the objects used as keys and values in the hash object, and thus is subject to the same documentation.

Upvotes: 2

0x000000
0x000000

Reputation: 86

No, it should not!

Different Ruby implementations (like jRuby, Rubinius, MRI 1.8.x, MRI 1.9.x etc) are using different ways to generate hashes. For example, for some objects (like you own classes or Hash instances) runtime will assign uniq and random id while creating this object. If I am not wrong, MRI tight works with hashes based on memory addresses: http://rxr.whitequark.org/mri/source/gc.c?v=1.8.7-p370#2111

So you can not guarantee that every run of your code will use the same random values or the same memory addresses every time.

Also I suggest to use ruby-doc instead of apidock for Ruby internals: http://ruby-doc.org/core-2.0/Object.html#method-i-hash

The hash value for an object may not be identical across invocations or implementations of ruby. If you need a stable identifier across ruby invocations and implementations you will need to generate one with a custom method.

Hope it will help you!

Upvotes: 7

Related Questions