hashdiff 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rubocop.yml +4 -0
- data/README.md +17 -13
- data/changelog.md +4 -0
- data/hashdiff.gemspec +1 -1
- data/lib/hashdiff/compare_hashes.rb +14 -1
- data/lib/hashdiff/diff.rb +3 -0
- data/lib/hashdiff/util.rb +2 -1
- data/lib/hashdiff/version.rb +1 -1
- data/spec/hashdiff/diff_spec.rb +5 -0
- data/spec/hashdiff/readme_spec.rb +15 -0
- data/spec/hashdiff/util_spec.rb +21 -0
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a9b50073f973250c144bb05272510f462dda18a7f5c9a8719156065773fdcaaa
|
4
|
+
data.tar.gz: 903439ed3ea22994d072201509506232fb77482506494bbb8c8419dc9fb8d546
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1c00d4710a67688a35197197da93ac3bfabca5f5a51edc152bfbd341a16548e762ddf2290364b7fc3a20e99cdb6d8d909ff84e766468fe623eb3977afd6d90f
|
7
|
+
data.tar.gz: 2d860929e99458cd89ee60ce877a87557d6bb9d52dcd25e0989f1a0a7b372d026bb646ee2b19498f6637a485f15fcd1e68cf1e1c0dbe666ad5af1792d60a893a
|
data/.rubocop.yml
CHANGED
@@ -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
|
-
```
|
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`,
|
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, :
|
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, :
|
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, :
|
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, :
|
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, :
|
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, :
|
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, :
|
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, :
|
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)
|
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
|
data/changelog.md
CHANGED
data/hashdiff.gemspec
CHANGED
@@ -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
|
-
|
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
|
data/lib/hashdiff/diff.rb
CHANGED
@@ -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,
|
data/lib/hashdiff/util.rb
CHANGED
@@ -16,7 +16,7 @@ module Hashdiff
|
|
16
16
|
|
17
17
|
diffs = count_diff diff(obja, objb, opts)
|
18
18
|
|
19
|
-
(1 - diffs
|
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)
|
data/lib/hashdiff/version.rb
CHANGED
data/spec/hashdiff/diff_spec.rb
CHANGED
@@ -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
|
data/spec/hashdiff/util_spec.rb
CHANGED
@@ -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.
|
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:
|
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:
|
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:
|
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
|
-
|
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.
|