From cbe656769500bfe59e09f22cf02a3e2b07e85163 Mon Sep 17 00:00:00 2001 From: Ettore Berardi Date: Wed, 8 Aug 2018 13:59:57 +0100 Subject: [PATCH 1/6] Fix signature mod between Ruby 2.1 and 2.4. For non Sting scalar values the object class gets injected in the signature data. Ruby 2.4 unified Fixnum and Bignum into Integer so a signature contening numbers in 2.1 will be different from one generated in 2.1. If you'll use Crimp to generate cache/database ids this can be a problem. This commit makes Crimp backward compatible. --- lib/crimp.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/crimp.rb b/lib/crimp.rb index ad75a86..b2dac8b 100644 --- a/lib/crimp.rb +++ b/lib/crimp.rb @@ -20,6 +20,8 @@ def self.convert(obj) parse_hash obj when String obj + when Integer + integer_to_string obj else to_string obj end @@ -46,4 +48,19 @@ def self.parse_hash(hash) def self.to_string(obj) "#{obj}#{obj.class}" 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.integer_to_string(obj) + "#{obj}Fixnum" + end end From 3418a90f29a49c45be720512f3f53a515a4b9c76 Mon Sep 17 00:00:00 2001 From: Ettore Berardi Date: Wed, 8 Aug 2018 14:06:24 +0100 Subject: [PATCH 2/6] Update JRuby version. Also to cope with TLSv1 issue. --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From deeeede139497655c8bb1cfce5c08603924e0e79 Mon Sep 17 00:00:00 2001 From: Ettore Berardi Date: Wed, 8 Aug 2018 14:07:44 +0100 Subject: [PATCH 3/6] Update maintainers email. --- crimp.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From e2002ac01465e4b50f4e8994a5c1b649dcce09ff Mon Sep 17 00:00:00 2001 From: Ettore Berardi Date: Wed, 8 Aug 2018 14:16:20 +0100 Subject: [PATCH 4/6] Increase Gem version. --- lib/crimp/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crimp/version.rb b/lib/crimp/version.rb index 0e6759f..b71c170 100644 --- a/lib/crimp/version.rb +++ b/lib/crimp/version.rb @@ -1,3 +1,3 @@ module Crimp - VERSION = '0.1.2'.freeze + VERSION = '1.0.0'.freeze end From cdbe0d920997b7fd5b640189825e5d18813b81c1 Mon Sep 17 00:00:00 2001 From: Ettore Berardi Date: Fri, 10 Aug 2018 11:04:28 +0100 Subject: [PATCH 5/6] Refactors tests. --- lib/crimp/version.rb | 2 +- spec/crimp_spec.rb | 37 +++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/crimp/version.rb b/lib/crimp/version.rb index b71c170..3092bd4 100644 --- a/lib/crimp/version.rb +++ b/lib/crimp/version.rb @@ -1,3 +1,3 @@ module Crimp - VERSION = '1.0.0'.freeze + VERSION = '0.2.0'.freeze end diff --git a/spec/crimp_spec.rb b/spec/crimp_spec.rb index bb96378..30a3d09 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,22 @@ expect(original_array).to eq(expected_array) end end + + context 'Given an integer' do + it 'returns MD5 hash of stringified Array' do + expect(subject.signature(123)).to eq '519d3381631851be66711f6d7dfbb4f8' + end + end + + context 'Given an float' do + it 'returns MD5 hash of stringified Array' 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 From 43bfa4f7ac6043715e92ab82f75730c14256e411 Mon Sep 17 00:00:00 2001 From: Ettore Berardi Date: Mon, 13 Aug 2018 13:41:25 +0100 Subject: [PATCH 6/6] Handles Bignums as if Ruby was stuck at 2.3 forever. --- lib/crimp.rb | 20 ++++++++++++++------ spec/crimp_spec.rb | 10 ++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/crimp.rb b/lib/crimp.rb index b2dac8b..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) @@ -20,8 +27,6 @@ def self.convert(obj) parse_hash obj when String obj - when Integer - integer_to_string obj else to_string obj end @@ -46,21 +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 + # 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.integer_to_string(obj) - "#{obj}Fixnum" + 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/spec/crimp_spec.rb b/spec/crimp_spec.rb index 30a3d09..623aa97 100644 --- a/spec/crimp_spec.rb +++ b/spec/crimp_spec.rb @@ -45,13 +45,19 @@ end context 'Given an integer' do - it 'returns MD5 hash of stringified Array' 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 stringified Array' do + it 'returns MD5 hash of a Float' do expect(subject.signature(3.14)).to eq 'b07d506e3701fddd083ae9095df43218' end end