hashdiff 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ad62d6aa698e908203a17f40c7660c49d8707cd0
4
- data.tar.gz: 34b23305366867798029b696354f0197571d3106
2
+ SHA256:
3
+ metadata.gz: a9b50073f973250c144bb05272510f462dda18a7f5c9a8719156065773fdcaaa
4
+ data.tar.gz: 903439ed3ea22994d072201509506232fb77482506494bbb8c8419dc9fb8d546
5
5
  SHA512:
6
- metadata.gz: 38621cceb7b659ec8a338edf712de931d06ea59aa18e8d9991262ed4f0b54bf1890c395d7a4391d325e82b05cdb7aa735cca2ef3a9aac1a991ec1f74a283e6b4
7
- data.tar.gz: 909dd874ea50b69bd74183e7df1cb0fd1c36e68b46810b0fbca32bc62111c5b2ff3899e5a7f72001c00df9b538195a7ecb57942d9c9fd640eb9bc639fd8358af
6
+ metadata.gz: e1c00d4710a67688a35197197da93ac3bfabca5f5a51edc152bfbd341a16548e762ddf2290364b7fc3a20e99cdb6d8d909ff84e766468fe623eb3977afd6d90f
7
+ data.tar.gz: 2d860929e99458cd89ee60ce877a87557d6bb9d52dcd25e0989f1a0a7b372d026bb646ee2b19498f6637a485f15fcd1e68cf1e1c0dbe666ad5af1792d60a893a
@@ -1,4 +1,6 @@
1
1
  require: rubocop-rspec
2
+ AllCops:
3
+ TargetRubyVersion: 2.0 # always the lowest version we support
2
4
  Metrics/PerceivedComplexity:
3
5
  Enabled: false
4
6
  Metrics/CyclomaticComplexity:
@@ -26,3 +28,5 @@ Style/RedundantFreeze:
26
28
  Enabled: false
27
29
  RSpec/ExampleLength:
28
30
  Enabled: false
31
+ RSpec/DescribeClass:
32
+ Enabled: false
data/README.md CHANGED
@@ -32,7 +32,7 @@ Hashdiff answers the question above using an opinionated approach:
32
32
 
33
33
  To use the gem, add the following to your Gemfile:
34
34
 
35
- ```ruby
35
+ ```Ruby
36
36
  gem 'hashdiff'
37
37
  ```
38
38
 
@@ -95,8 +95,8 @@ Hashdiff.unpatch!(b, diff).should == a
95
95
  ### Options
96
96
 
97
97
  There are eight options available: `:delimiter`, `:similarity`,
98
- `:strict`, `:numeric_tolerance`, `:strip`, `:case_insensitive`, `:array_path`
99
- and `:use_lcs`
98
+ `:strict`, `:indifferent`, `:numeric_tolerance`, `:strip`, `:case_insensitive`,
99
+ `:array_path` and `:use_lcs`
100
100
 
101
101
  #### `:delimiter`
102
102
 
@@ -106,7 +106,7 @@ You can specify `:delimiter` to be something other than the default dot. For exa
106
106
  a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
107
107
  b = {a:{y:3}, b:{y:3, z:30}}
108
108
 
109
- diff = Hashdiff.diff(a, b, :delimiter => '\t')
109
+ diff = Hashdiff.diff(a, b, delimiter: '\t')
110
110
  diff.should == [['-', 'a\tx', 2], ['-', 'a\tz', 4], ['-', 'b\tx', 3], ['~', 'b\tz', 45, 30], ['+', 'b\ty', 3]]
111
111
  ```
112
112
 
@@ -118,6 +118,10 @@ In cases where you have similar hash objects in arrays, you can pass a custom va
118
118
 
119
119
  The `:strict` option, which defaults to `true`, specifies whether numeric types are compared on type as well as value. By default, an Integer will never be equal to a Float (e.g. 4 != 4.0). Setting `:strict` to false makes the comparison looser (e.g. 4 == 4.0).
120
120
 
121
+ #### `:indifferent`
122
+
123
+ The `:indifferent` option, which defaults to `false`, specifies whether to treat hash keys indifferently. Setting `:indifferent` to true has the effect of ignoring differences between symbol keys (ie. {a: 1} ~= {'a' => 1})
124
+
121
125
  #### `:numeric_tolerance`
122
126
 
123
127
  The :numeric_tolerance option allows for a small numeric tolerance.
@@ -126,7 +130,7 @@ The :numeric_tolerance option allows for a small numeric tolerance.
126
130
  a = {x:5, y:3.75, z:7}
127
131
  b = {x:6, y:3.76, z:7}
128
132
 
129
- diff = Hashdiff.diff(a, b, :numeric_tolerance => 0.1)
133
+ diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1)
130
134
  diff.should == [["~", "x", 5, 6]]
131
135
  ```
132
136
 
@@ -138,7 +142,7 @@ The :strip option strips all strings before comparing.
138
142
  a = {x:5, s:'foo '}
139
143
  b = {x:6, s:'foo'}
140
144
 
141
- diff = Hashdiff.diff(a, b, :comparison => { :numeric_tolerance => 0.1, :strip => true })
145
+ diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1, strip: true)
142
146
  diff.should == [["~", "x", 5, 6]]
143
147
  ```
144
148
 
@@ -150,7 +154,7 @@ The :case_insensitive option makes string comparisons ignore case.
150
154
  a = {x:5, s:'FooBar'}
151
155
  b = {x:6, s:'foobar'}
152
156
 
153
- diff = Hashdiff.diff(a, b, :comparison => { :numeric_tolerance => 0.1, :case_insensitive => true })
157
+ diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1, case_insensitive: true)
154
158
  diff.should == [["~", "x", 5, 6]]
155
159
  ```
156
160
 
@@ -164,7 +168,7 @@ is useful for `patch!` when used on hashes without string keys.
164
168
  a = {x:5}
165
169
  b = {'x'=>6}
166
170
 
167
- diff = Hashdiff.diff(a, b, :array_path => true)
171
+ diff = Hashdiff.diff(a, b, array_path: true)
168
172
  diff.should == [['-', [:x], 5], ['+', ['x'], 6]]
169
173
  ```
170
174
 
@@ -173,7 +177,7 @@ For cases where there are arrays in paths their index will be added to the path.
173
177
  a = {x:[0,1]}
174
178
  b = {x:[0,2]}
175
179
 
176
- diff = Hashdiff.diff(a, b, :array_path => true)
180
+ diff = Hashdiff.diff(a, b, array_path: true)
177
181
  diff.should == [["-", [:x, 1], 1], ["+", [:x, 1], 2]]
178
182
  ```
179
183
 
@@ -183,7 +187,7 @@ This shouldn't cause problems if you are comparing an array with a hash:
183
187
  a = {x:{0=>1}}
184
188
  b = {x:[1]}
185
189
 
186
- diff = Hashdiff.diff(a, b, :array_path => true)
190
+ diff = Hashdiff.diff(a, b, array_path: true)
187
191
  diff.should == [["~", [:x], {0=>1}, [1]]]
188
192
  ```
189
193
 
@@ -205,7 +209,7 @@ Note, currently the :similarity option has no effect when :use_lcs is false.
205
209
  a = {x: [0, 1, 2]}
206
210
  b = {x: [0, 2, 2, 3]}
207
211
 
208
- diff = Hashdiff.diff(a, b, :use_lcs => false)
212
+ diff = Hashdiff.diff(a, b, use_lcs: false)
209
213
  diff.should == [["~", "x[1]", 1, 2], ["+", "x[3]", 3]]
210
214
  ```
211
215
 
@@ -255,11 +259,11 @@ An order difference alone between two arrays can create too many diffs to be use
255
259
  a = {a:'car', b:['boat', 'plane'] }
256
260
  b = {a:'car', b:['plane', 'boat'] }
257
261
 
258
- Hashdiff.diff(a, b) => [["+", "b[0]", "plane"], ["-", "b[2]", "plane"]]
262
+ Hashdiff.diff(a, b).should == [["+", "b[0]", "plane"], ["-", "b[2]", "plane"]]
259
263
 
260
264
  b[:b].sort!
261
265
 
262
- Hashdiff.diff(a, b) => []
266
+ Hashdiff.diff(a, b).should == []
263
267
  ```
264
268
 
265
269
  ## Maintainers
@@ -1,5 +1,9 @@
1
1
  # Change Log
2
2
 
3
+ ## v1.0.1 2020-02-25
4
+
5
+ * Add indifferent option
6
+
3
7
  ## v1.0.0 2019-06-06
4
8
 
5
9
  * Fix typo in readme (#72 @koic)
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.add_development_dependency('bluecloth')
25
25
  s.add_development_dependency('rspec', '~> 2.0')
26
- s.add_development_dependency('rubocop')
26
+ s.add_development_dependency('rubocop', '~> 0.49.1') # last version that works with ruby 2.0
27
27
  s.add_development_dependency('rubocop-rspec')
28
28
  s.add_development_dependency('yard')
29
29
 
@@ -10,6 +10,15 @@ module Hashdiff
10
10
 
11
11
  obj1_keys = obj1.keys
12
12
  obj2_keys = obj2.keys
13
+ obj1_lookup = {}
14
+ obj2_lookup = {}
15
+
16
+ if opts[:indifferent]
17
+ obj1_lookup = obj1_keys.each_with_object({}) { |k, h| h[k.to_s] = k }
18
+ obj2_lookup = obj2_keys.each_with_object({}) { |k, h| h[k.to_s] = k }
19
+ obj1_keys = obj1_keys.map { |k| k.is_a?(Symbol) ? k.to_s : k }
20
+ obj2_keys = obj2_keys.map { |k| k.is_a?(Symbol) ? k.to_s : k }
21
+ end
13
22
 
14
23
  added_keys = (obj2_keys - obj1_keys).sort_by(&:to_s)
15
24
  common_keys = (obj1_keys & obj2_keys).sort_by(&:to_s)
@@ -19,6 +28,7 @@ module Hashdiff
19
28
 
20
29
  # add deleted properties
21
30
  deleted_keys.each do |k|
31
+ k = opts[:indifferent] ? obj1_lookup[k] : k
22
32
  change_key = Hashdiff.prefix_append_key(opts[:prefix], k, opts)
23
33
  custom_result = Hashdiff.custom_compare(opts[:comparison], change_key, obj1[k], nil)
24
34
 
@@ -33,13 +43,16 @@ module Hashdiff
33
43
  common_keys.each do |k|
34
44
  prefix = Hashdiff.prefix_append_key(opts[:prefix], k, opts)
35
45
 
36
- result.concat(Hashdiff.diff(obj1[k], obj2[k], opts.merge(prefix: prefix)))
46
+ k1 = opts[:indifferent] ? obj1_lookup[k] : k
47
+ k2 = opts[:indifferent] ? obj2_lookup[k] : k
48
+ result.concat(Hashdiff.diff(obj1[k1], obj2[k2], opts.merge(prefix: prefix)))
37
49
  end
38
50
 
39
51
  # added properties
40
52
  added_keys.each do |k|
41
53
  change_key = Hashdiff.prefix_append_key(opts[:prefix], k, opts)
42
54
 
55
+ k = opts[:indifferent] ? obj2_lookup[k] : k
43
56
  custom_result = Hashdiff.custom_compare(opts[:comparison], change_key, nil, obj2[k])
44
57
 
45
58
  if custom_result
@@ -9,6 +9,7 @@ module Hashdiff
9
9
  # @param [Array, Hash] obj2
10
10
  # @param [Hash] options the options to use when comparing
11
11
  # * :strict (Boolean) [true] whether numeric values will be compared on type as well as value. Set to false to allow comparing Integer, Float, BigDecimal to each other
12
+ # * :indifferent (Boolean) [false] whether to treat hash keys indifferently. Set to true to ignore differences between symbol keys (ie. {a: 1} ~= {'a' => 1})
12
13
  # * :delimiter (String) ['.'] the delimiter used when returning nested key references
13
14
  # * :numeric_tolerance (Numeric) [0] should be a positive numeric value. Value by which numeric differences must be greater than. By default, numeric values are compared exactly; with the :tolerance option, the difference between numeric values must be greater than the given value.
14
15
  # * :strip (Boolean) [false] whether or not to call #strip on strings before comparing
@@ -52,6 +53,7 @@ module Hashdiff
52
53
  # @param [Array, Hash] obj2
53
54
  # @param [Hash] options the options to use when comparing
54
55
  # * :strict (Boolean) [true] whether numeric values will be compared on type as well as value. Set to false to allow comparing Integer, Float, BigDecimal to each other
56
+ # * :indifferent (Boolean) [false] whether to treat hash keys indifferently. Set to true to ignore differences between symbol keys (ie. {a: 1} ~= {'a' => 1})
55
57
  # * :similarity (Numeric) [0.8] should be between (0, 1]. Meaningful if there are similar hashes in arrays. See {best_diff}.
56
58
  # * :delimiter (String) ['.'] the delimiter used when returning nested key references
57
59
  # * :numeric_tolerance (Numeric) [0] should be a positive numeric value. Value by which numeric differences must be greater than. By default, numeric values are compared exactly; with the :tolerance option, the difference between numeric values must be greater than the given value.
@@ -79,6 +81,7 @@ module Hashdiff
79
81
  similarity: 0.8,
80
82
  delimiter: '.',
81
83
  strict: true,
84
+ indifferent: false,
82
85
  strip: false,
83
86
  numeric_tolerance: 0,
84
87
  array_path: false,
@@ -16,7 +16,7 @@ module Hashdiff
16
16
 
17
17
  diffs = count_diff diff(obja, objb, opts)
18
18
 
19
- (1 - diffs.to_f / (count_a + count_b).to_f) >= opts[:similarity]
19
+ (1 - diffs / (count_a + count_b).to_f) >= opts[:similarity]
20
20
  end
21
21
 
22
22
  # @private
@@ -107,6 +107,7 @@ module Hashdiff
107
107
  # check if objects are comparable
108
108
  def self.comparable?(obj1, obj2, strict = true)
109
109
  return true if (obj1.is_a?(Array) || obj1.is_a?(Hash)) && obj2.is_a?(obj1.class)
110
+ return true if (obj2.is_a?(Array) || obj2.is_a?(Hash)) && obj1.is_a?(obj2.class)
110
111
  return true if !strict && obj1.is_a?(Numeric) && obj2.is_a?(Numeric)
111
112
 
112
113
  obj1.is_a?(obj2.class) && obj2.is_a?(obj1.class)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hashdiff
4
- VERSION = '1.0.0'.freeze
4
+ VERSION = '1.0.1'.freeze
5
5
  end
@@ -49,6 +49,11 @@ describe Hashdiff do
49
49
  diff.should == []
50
50
  end
51
51
 
52
+ it 'ignores string vs symbol differences, when indifferent is true' do
53
+ diff = described_class.diff({ 'a' => 2, :b => 2 }, { :a => 2, 'b' => 2, :c => 3 }, indifferent: true)
54
+ diff.should == [['+', 'c', 3]]
55
+ end
56
+
52
57
  it 'is able to diff changes in hash value' do
53
58
  diff = described_class.diff({ 'a' => 2, 'b' => 3, 'c' => ' hello' }, 'a' => 2, 'b' => 4, 'c' => 'hello')
54
59
  diff.should == [['~', 'b', 3, 4], ['~', 'c', ' hello', 'hello']]
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'README.md' do
6
+ it 'has correct examples' do
7
+ File.read('README.md').scan(/```ruby(.*?)```/m).flatten(1).each do |block|
8
+ begin
9
+ eval block # rubocop:disable Security/Eval
10
+ rescue Exception => e # rubocop:disable Lint/RescueException
11
+ raise "README.md code block:\n#{block}\n\nhas error:\n#{e}"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -68,6 +68,7 @@ describe Hashdiff do
68
68
  it 'compares different objects without tolerance' do
69
69
  expect(described_class.compare_values('hats', 'ninjas')).to be false
70
70
  end
71
+
71
72
  it 'compares other objects with tolerance' do
72
73
  expect(described_class.compare_values('hats', 'ninjas', numeric_tolerance: 0.01)).to be false
73
74
  end
@@ -92,4 +93,24 @@ describe Hashdiff do
92
93
  expect(described_class.compare_values('horse', 'Horse', case_insensitive: true)).to be true
93
94
  end
94
95
  end
96
+
97
+ describe '.comparable?' do
98
+ it 'identifies hashes as comparable' do
99
+ expect(described_class.comparable?({}, {})).to be true
100
+ end
101
+
102
+ it 'identifies a subclass of Hash to be comparable with a Hash' do
103
+ other = Class.new(Hash)
104
+ expect(described_class.comparable?(other.new, {})).to be true
105
+ end
106
+
107
+ it 'identifies a Hash to be comparable with a subclass of Hash' do
108
+ other = Class.new(Hash)
109
+ expect(described_class.comparable?({}, other.new)).to be true
110
+ end
111
+
112
+ it 'does not identify a Numeric as comparable with a Hash' do
113
+ expect(described_class.comparable?(1, {})).to be false
114
+ end
115
+ end
95
116
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hashdiff
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Fengyun
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-15 00:00:00.000000000 Z
11
+ date: 2020-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bluecloth
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.49.1
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.49.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rubocop-rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -114,6 +114,7 @@ files:
114
114
  - spec/hashdiff/lcs_spec.rb
115
115
  - spec/hashdiff/linear_compare_array_spec.rb
116
116
  - spec/hashdiff/patch_spec.rb
117
+ - spec/hashdiff/readme_spec.rb
117
118
  - spec/hashdiff/util_spec.rb
118
119
  - spec/spec_helper.rb
119
120
  homepage: https://github.com/liufengyun/hashdiff
@@ -140,8 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
141
  - !ruby/object:Gem::Version
141
142
  version: '0'
142
143
  requirements: []
143
- rubyforge_project:
144
- rubygems_version: 2.5.2.3
144
+ rubygems_version: 3.0.6
145
145
  signing_key:
146
146
  specification_version: 4
147
147
  summary: Hashdiff is a diff lib to compute the smallest difference between two hashes.