This project is archived and is in readonly mode.
Consistent Integer Values Using Fixtures.identify In Ruby1.9
Reported by Ken Collins | May 11th, 2009 @ 04:17 PM | in 2.x
Fixtures.identify is no longer working on 1.9 since it returns a different integer each time it's run. This is a change in ruby core that brought this about and I see no clear solution. Example code.
# Ruby 1.8.x
$ irb1.8
irb(main):001:0> 'admin'.hash.abs # => 541702176
irb(main):002:0> exit
$ irb1.8
irb(main):001:0> 'admin'.hash.abs # => 541702176
# Ruby 1.9.x
$ irb1.9
irb(main):001:0> 'admin'.hash.abs # => 382338625
irb(main):002:0> exit
$ irb1.9
irb(main):001:0> 'admin'.hash.abs # => 542676158
# Proposed usage of String#sum
$ irb1.9
irb(main):001:0> 'admin'.sum # => 521
I have attached a patch, but it has no tests because I can not think of a good way to cleanly call another process. I'd like input on a test method to add and even if using String#sum might be the right way to go.
Comments and changes to this ticket
-
Frederick Cheung May 11th, 2009 @ 04:25 PM
You're going to get a lot of collisions like that eg
'foo'.sum == 'oof'.sum
If we truly need fixture identifiers that persist across runs, i think that taking the top few bytes from a cryptographic hash (or just reimplement the old hash algorithm from ruby 1.8) would be preferable.
-
Ken Collins May 11th, 2009 @ 04:48 PM
I'd love to see a re-implementation of pre 1.9 String#hash, I'm looking at the bits of C code I pulled from source here.
I'm new to C, but I'm playing with converting this to ruby now.
-
Frederick Cheung May 11th, 2009 @ 06:34 PM
Part of the problem is that the integer overflows, and according to the c standard an overflowing signed integer has undefined behaviour, so this may be harder than I initially thought
-
Jeremy Kemper May 11th, 2009 @ 09:52 PM
Perhaps better to just switch to a consistent hash or crc value now.
-
Frederick Cheung May 11th, 2009 @ 10:46 PM
I'm assuming no-one actually cares what the actual value of Fixture.identify('foo') is, as long as it doesn't change across test runs - I don't think changing this would screw people over. (I'm not even sure why Fixture.identify changing between test runs is a problem - it's only needed to load the fixtures)
-
Ken Collins May 11th, 2009 @ 11:08 PM
@Jeremy Could you give me an example of a crc value? I'm having a hard time thinking of how to get a consistent fixnum representation from a string.
@Frederick Your right, I could care less if this id returned is the same as ruby 1.8. My code is abstract so that I never got bit by this. But I do need consistent values for quite a few reasons.
Again, any implementation help would be appreciated. I might take a stab at this again tomorrow using the bytes somehow.
-
Ken Collins May 12th, 2009 @ 12:28 AM
OK, here is v2 of the patch. I'm using Zlib like Jeremy suggested. The only problem I ran into is that the default crc32 method could generate a bignum that is out of bounds for my primary keys. So I had to take it down a few notches. I guess it's theoretically possible that some keys could duplicate, but I doubt it would be a problem. Thoughts if any?
I added a few tests that possibly help standardize this internal implementation. All tests pass under 1.9 and 1.8.
-
Ken Collins May 12th, 2009 @ 01:41 AM
I'd hold off on this one too... I'm having issue under the SQL Server adapter since the values might be too big there too.
-
Ken Collins May 12th, 2009 @ 03:38 AM
OK, this one passes all the DB tests, most importantly PostgreSQL.
-
Jeremy Kemper May 12th, 2009 @ 04:01 AM
How about:
MAX_ID = 2 ** 31 - 1 def self.identify(label) Zlib.crc32(label.to_s) % MAX_ID end
-
Frederick Cheung May 12th, 2009 @ 09:00 AM
You will occasionally get duplicate values but that happened with the old hash too and is inevitable (pigeon hole principal etc.)
-
Brennan Dunn May 18th, 2009 @ 06:28 PM
+1 - the ID generated from a fixture's name should remain consistent across runs, IMO.
-
Repository May 18th, 2009 @ 11:01 PM
- State changed from new to committed
(from [50608ecccdda7c3709c61484653f9ebb17068fcf]) Reimplement Fixtures.identify so that it consistently generates identities across ruby versions.
[#2633 state:committed]
Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
http://github.com/rails/rails/commit/50608ecccdda7c3709c61484653f9e... -
Repository May 18th, 2009 @ 11:02 PM
(from [87adecfef59577be17a9731245cb201ecb1b477f]) Reimplement Fixtures.identify so that it consistently generates identities across ruby versions.
[#2633 state:committed]
Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
http://github.com/rails/rails/commit/87adecfef59577be17a9731245cb20...
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>
People watching this ticket
Attachments
Referenced by
- 2633 Consistent Integer Values Using Fixtures.identify In Ruby1.9 [#2633 state:committed]
- 2633 Consistent Integer Values Using Fixtures.identify In Ruby1.9 [#2633 state:committed]