diff --git a/.ruby-version b/.ruby-version index 3f36e23..99a49eb 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -jruby-1.7.17 +jruby-1.7.23 diff --git a/crimp.gemspec b/crimp.gemspec index 2704f12..e61bd40 100644 --- a/crimp.gemspec +++ b/crimp.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |spec| spec.name = "crimp" spec.version = Crimp::VERSION spec.authors = ["BBC News"] - spec.email = ["FutureMediaNewsRubyGems@bbc.co.uk"] + spec.email = ["D&ENewsFrameworksTeam@bbc.co.uk"] spec.summary = %q{Creating an md5 hash of a number, string, array, or hash in Ruby} spec.description = <<-EOS.gsub /^\s+/, "" Shamelessly lifted from http://stackoverflow.com/questions/6461812/creating-an-md5-hash-of-a-number-string-array-or-hash-in-ruby diff --git a/lib/crimp.rb b/lib/crimp.rb index ad75a86..e39d8ea 100644 --- a/lib/crimp.rb +++ b/lib/crimp.rb @@ -1,6 +1,13 @@ require 'crimp/version' require 'digest' +class Numeric + # see http://patshaughnessy.net/2014/1/9/how-big-is-a-bignum + def bignum? + self >= 4611686018427387904 + end +end + module Crimp def self.signature(obj) Digest::MD5.hexdigest stringify(obj) @@ -44,6 +51,24 @@ def self.parse_hash(hash) end def self.to_string(obj) - "#{obj}#{obj.class}" + "#{obj}#{legacy_class(obj)}" + end + + # This is for legacy/compatibilty reason: + # + # Ruby 2.1 + # 2.class => Fixnum + # Ruby >= 2.4 + # 2.class => Integer + # + # Say you have a huge number of stored keys and you migrate your app from 2.1 to >= 2.4 + # this would cause a change of the signature for a subset of the keys which would be hard + # to debug especially for nested data structures. + # + def self.legacy_class(obj) + return obj.class unless obj.is_a?(Numeric) + return 'Float' if obj.is_a?(Float) + return 'Bignum' if obj.bignum? + 'Fixnum' end end diff --git a/lib/crimp/version.rb b/lib/crimp/version.rb index 0e6759f..3092bd4 100644 --- a/lib/crimp/version.rb +++ b/lib/crimp/version.rb @@ -1,3 +1,3 @@ module Crimp - VERSION = '0.1.2'.freeze + VERSION = '0.2.0'.freeze end diff --git a/spec/crimp_spec.rb b/spec/crimp_spec.rb index bb96378..623aa97 100644 --- a/spec/crimp_spec.rb +++ b/spec/crimp_spec.rb @@ -1,17 +1,16 @@ require 'spec_helper' describe Crimp do - let (:hash) { { a: { b: 'b', c: 'c' }, d: 'd' } } - let (:hash_unordered) { { d: 'd', a: { c: 'c', b: 'b' } } } - let (:array) { [1, 2, 3, [4, [5, 6]]] } - let (:array_unordered) { [3, 2, 1, [[5, 6], 4]] } + let(:hash) { { a: { b: 'b', c: 'c' }, d: 'd' } } + let(:hash_with_numbers) { { a: { b: 1, c: 3.14 }, d: 'd' } } + let(:hash_unordered) { { d: 'd', a: { c: 'c', b: 'b' } } } + let(:array) { [1, 2, 3, [4, [5, 6]]] } + let(:array_unordered) { [3, 2, 1, [[5, 6], 4]] } describe '.signature' do context 'given a Hash' do - specify { expect(subject.signature(hash)).to be_a String } - it 'returns MD5 hash of stringified Hash' do - expect(subject.signature(hash)).to eq(Digest::MD5.hexdigest(subject.stringify(hash))) + expect(subject.signature(hash)).to eq('68d07febc4f47f56fa6ef5de063a77b1') end it 'does not modify original hash' do @@ -24,11 +23,15 @@ end end - context 'given an Array' do - specify { expect(subject.signature(array)).to be_a String } + context 'Given an hash with numbers' do + it 'returns MD5 hash of stringified hash' do + expect(subject.signature(hash_with_numbers)).to eq 'b1fec09904b6ff36c92e3bd48234def7' + end + end + context 'given an Array' do it 'returns MD5 hash of stringified Array' do - expect(subject.signature(array)).to eq(Digest::MD5.hexdigest(subject.stringify(array))) + expect(subject.signature(array)).to eq('4dc4e1161c9315db0bc43c0201b3ec05') end it 'does not modify original array' do @@ -40,12 +43,28 @@ expect(original_array).to eq(expected_array) end end + + context 'Given an integer' do + it 'returns MD5 hash of an Integer' do + expect(subject.signature(123)).to eq '519d3381631851be66711f6d7dfbb4f8' + end + end + + context 'Given an Bignum' do + it 'returns MD5 hash of a Bignum' do + expect(subject.signature(9999999999999999999)).to eq 'f00e75abca720e18fd4213e2a6de96c6' + end + end + + context 'Given an float' do + it 'returns MD5 hash of a Float' do + expect(subject.signature(3.14)).to eq 'b07d506e3701fddd083ae9095df43218' + end + end end describe '.stringify' do context 'given a Hash' do - specify { expect(subject.stringify(hash)).to be_a String } - it 'returns equal strings for differently ordered hashes' do expect(subject.stringify(hash)).to eq(subject.stringify(hash_unordered)) end