hashdiff 0.3.7 → 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 +32 -0
- data/.travis.yml +3 -5
- data/Gemfile +3 -1
- data/README.md +42 -31
- data/Rakefile +9 -4
- data/changelog.md +31 -3
- data/hashdiff.gemspec +26 -12
- data/lib/hashdiff.rb +4 -0
- data/lib/hashdiff/compare_hashes.rb +69 -0
- data/lib/hashdiff/diff.rb +61 -116
- data/lib/hashdiff/lcs.rb +27 -30
- data/lib/hashdiff/lcs_compare_arrays.rb +32 -0
- data/lib/hashdiff/linear_compare_array.rb +10 -6
- data/lib/hashdiff/patch.rb +5 -5
- data/lib/hashdiff/util.rb +44 -35
- data/lib/hashdiff/version.rb +4 -2
- data/spec/hashdiff/best_diff_spec.rb +44 -43
- data/spec/hashdiff/diff_array_spec.rb +19 -19
- data/spec/hashdiff/diff_spec.rb +180 -159
- data/spec/hashdiff/lcs_spec.rb +27 -26
- data/spec/hashdiff/linear_compare_array_spec.rb +20 -18
- data/spec/hashdiff/patch_spec.rb +123 -121
- data/spec/hashdiff/readme_spec.rb +15 -0
- data/spec/hashdiff/util_spec.rb +81 -43
- data/spec/spec_helper.rb +2 -0
- metadata +59 -23
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
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
AllCops:
|
3
|
+
TargetRubyVersion: 2.0 # always the lowest version we support
|
4
|
+
Metrics/PerceivedComplexity:
|
5
|
+
Enabled: false
|
6
|
+
Metrics/CyclomaticComplexity:
|
7
|
+
Enabled: false
|
8
|
+
Metrics/MethodLength:
|
9
|
+
Enabled: false
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Enabled: false
|
12
|
+
Metrics/LineLength:
|
13
|
+
Enabled: false
|
14
|
+
Metrics/ClassLength:
|
15
|
+
Enabled: false
|
16
|
+
Metrics/BlockLength:
|
17
|
+
Enabled: false
|
18
|
+
Metrics/ModuleLength:
|
19
|
+
Enabled: false
|
20
|
+
Style/Documentation:
|
21
|
+
Enabled: false
|
22
|
+
Style/FrozenStringLiteralComment:
|
23
|
+
Enabled: true
|
24
|
+
EnforcedStyle: always
|
25
|
+
Style/NumericPredicate:
|
26
|
+
Enabled: false
|
27
|
+
Style/RedundantFreeze:
|
28
|
+
Enabled: false
|
29
|
+
RSpec/ExampleLength:
|
30
|
+
Enabled: false
|
31
|
+
RSpec/DescribeClass:
|
32
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
-
#
|
1
|
+
# Hashdiff [](http://travis-ci.org/liufengyun/hashdiff) [](http://badge.fury.io/rb/hashdiff)
|
2
2
|
|
3
|
-
|
3
|
+
Hashdiff is a ruby library to compute the smallest difference between two hashes.
|
4
4
|
|
5
5
|
It also supports comparing two arrays.
|
6
6
|
|
7
|
-
|
7
|
+
Hashdiff does not monkey-patch any existing class. All features are contained inside the `Hashdiff` module.
|
8
8
|
|
9
9
|
**Docs**: [Documentation](http://rubydoc.info/gems/hashdiff)
|
10
10
|
|
11
|
-
|
11
|
+
|
12
|
+
__WARNING__: Don't use the library for comparing large arrays, say ~10K (see #49).
|
13
|
+
|
14
|
+
## Why Hashdiff?
|
12
15
|
|
13
16
|
Given two Hashes A and B, sometimes you face the question: what's the smallest modification that can be made to change A into B?
|
14
17
|
|
@@ -18,7 +21,7 @@ An algorithm that responds to this question has to do following:
|
|
18
21
|
* Compute recursively -- Arrays and Hashes may be nested arbitrarily in A or B.
|
19
22
|
* Compute the smallest change -- it should recognize similar child Hashes or child Arrays between A and B.
|
20
23
|
|
21
|
-
|
24
|
+
Hashdiff answers the question above using an opinionated approach:
|
22
25
|
|
23
26
|
* Hash can be represented as a list of (dot-syntax-path, value) pairs. For example, `{a:[{c:2}]}` can be represented as `["a[0].c", 2]`.
|
24
27
|
* The change set can be represented using the dot-syntax representation. For example, `[['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]`.
|
@@ -29,7 +32,7 @@ HashDiff answers the question above using an opinionated approach:
|
|
29
32
|
|
30
33
|
To use the gem, add the following to your Gemfile:
|
31
34
|
|
32
|
-
```
|
35
|
+
```Ruby
|
33
36
|
gem 'hashdiff'
|
34
37
|
```
|
35
38
|
|
@@ -43,7 +46,7 @@ Two simple hashes:
|
|
43
46
|
a = {a:3, b:2}
|
44
47
|
b = {}
|
45
48
|
|
46
|
-
diff =
|
49
|
+
diff = Hashdiff.diff(a, b)
|
47
50
|
diff.should == [['-', 'a', 3], ['-', 'b', 2]]
|
48
51
|
```
|
49
52
|
|
@@ -53,7 +56,7 @@ More complex hashes:
|
|
53
56
|
a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
|
54
57
|
b = {a:{y:3}, b:{y:3, z:30}}
|
55
58
|
|
56
|
-
diff =
|
59
|
+
diff = Hashdiff.diff(a, b)
|
57
60
|
diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]
|
58
61
|
```
|
59
62
|
|
@@ -63,7 +66,7 @@ Arrays in hashes:
|
|
63
66
|
a = {a:[{x:2, y:3, z:4}, {x:11, y:22, z:33}], b:{x:3, z:45}}
|
64
67
|
b = {a:[{y:3}, {x:11, z:33}], b:{y:22}}
|
65
68
|
|
66
|
-
diff =
|
69
|
+
diff = Hashdiff.best_diff(a, b)
|
67
70
|
diff.should == [['-', 'a[0].x', 2], ['-', 'a[0].z', 4], ['-', 'a[1].y', 22], ['-', 'b.x', 3], ['-', 'b.z', 45], ['+', 'b.y', 22]]
|
68
71
|
```
|
69
72
|
|
@@ -75,8 +78,8 @@ patch example:
|
|
75
78
|
a = {'a' => 3}
|
76
79
|
b = {'a' => {'a1' => 1, 'a2' => 2}}
|
77
80
|
|
78
|
-
diff =
|
79
|
-
|
81
|
+
diff = Hashdiff.diff(a, b)
|
82
|
+
Hashdiff.patch!(a, diff).should == b
|
80
83
|
```
|
81
84
|
|
82
85
|
unpatch example:
|
@@ -85,15 +88,15 @@ unpatch example:
|
|
85
88
|
a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, {'x' => 5, 'y' => 6, 'z' => 3}, 1]
|
86
89
|
b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
|
87
90
|
|
88
|
-
diff =
|
89
|
-
|
91
|
+
diff = Hashdiff.diff(a, b) # diff two array is OK
|
92
|
+
Hashdiff.unpatch!(b, diff).should == a
|
90
93
|
```
|
91
94
|
|
92
95
|
### Options
|
93
96
|
|
94
97
|
There are eight options available: `:delimiter`, `:similarity`,
|
95
|
-
`:strict`, `:numeric_tolerance`, `:strip`, `:case_insensitive`,
|
96
|
-
and `:use_lcs`
|
98
|
+
`:strict`, `:indifferent`, `:numeric_tolerance`, `:strip`, `:case_insensitive`,
|
99
|
+
`:array_path` and `:use_lcs`
|
97
100
|
|
98
101
|
#### `:delimiter`
|
99
102
|
|
@@ -103,7 +106,7 @@ You can specify `:delimiter` to be something other than the default dot. For exa
|
|
103
106
|
a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
|
104
107
|
b = {a:{y:3}, b:{y:3, z:30}}
|
105
108
|
|
106
|
-
diff =
|
109
|
+
diff = Hashdiff.diff(a, b, delimiter: '\t')
|
107
110
|
diff.should == [['-', 'a\tx', 2], ['-', 'a\tz', 4], ['-', 'b\tx', 3], ['~', 'b\tz', 45, 30], ['+', 'b\ty', 3]]
|
108
111
|
```
|
109
112
|
|
@@ -113,7 +116,11 @@ In cases where you have similar hash objects in arrays, you can pass a custom va
|
|
113
116
|
|
114
117
|
#### `:strict`
|
115
118
|
|
116
|
-
The `:strict` option, which defaults to `true`, specifies whether numeric types are compared on type as well as value. By default,
|
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
|
+
|
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})
|
117
124
|
|
118
125
|
#### `:numeric_tolerance`
|
119
126
|
|
@@ -123,7 +130,7 @@ The :numeric_tolerance option allows for a small numeric tolerance.
|
|
123
130
|
a = {x:5, y:3.75, z:7}
|
124
131
|
b = {x:6, y:3.76, z:7}
|
125
132
|
|
126
|
-
diff =
|
133
|
+
diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1)
|
127
134
|
diff.should == [["~", "x", 5, 6]]
|
128
135
|
```
|
129
136
|
|
@@ -135,7 +142,7 @@ The :strip option strips all strings before comparing.
|
|
135
142
|
a = {x:5, s:'foo '}
|
136
143
|
b = {x:6, s:'foo'}
|
137
144
|
|
138
|
-
diff =
|
145
|
+
diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1, strip: true)
|
139
146
|
diff.should == [["~", "x", 5, 6]]
|
140
147
|
```
|
141
148
|
|
@@ -147,7 +154,7 @@ The :case_insensitive option makes string comparisons ignore case.
|
|
147
154
|
a = {x:5, s:'FooBar'}
|
148
155
|
b = {x:6, s:'foobar'}
|
149
156
|
|
150
|
-
diff =
|
157
|
+
diff = Hashdiff.diff(a, b, numeric_tolerance: 0.1, case_insensitive: true)
|
151
158
|
diff.should == [["~", "x", 5, 6]]
|
152
159
|
```
|
153
160
|
|
@@ -161,7 +168,7 @@ is useful for `patch!` when used on hashes without string keys.
|
|
161
168
|
a = {x:5}
|
162
169
|
b = {'x'=>6}
|
163
170
|
|
164
|
-
diff =
|
171
|
+
diff = Hashdiff.diff(a, b, array_path: true)
|
165
172
|
diff.should == [['-', [:x], 5], ['+', ['x'], 6]]
|
166
173
|
```
|
167
174
|
|
@@ -170,7 +177,7 @@ For cases where there are arrays in paths their index will be added to the path.
|
|
170
177
|
a = {x:[0,1]}
|
171
178
|
b = {x:[0,2]}
|
172
179
|
|
173
|
-
diff =
|
180
|
+
diff = Hashdiff.diff(a, b, array_path: true)
|
174
181
|
diff.should == [["-", [:x, 1], 1], ["+", [:x, 1], 2]]
|
175
182
|
```
|
176
183
|
|
@@ -180,8 +187,8 @@ This shouldn't cause problems if you are comparing an array with a hash:
|
|
180
187
|
a = {x:{0=>1}}
|
181
188
|
b = {x:[1]}
|
182
189
|
|
183
|
-
diff =
|
184
|
-
diff.should == [["~", [:
|
190
|
+
diff = Hashdiff.diff(a, b, array_path: true)
|
191
|
+
diff.should == [["~", [:x], {0=>1}, [1]]]
|
185
192
|
```
|
186
193
|
|
187
194
|
#### `:use_lcs`
|
@@ -202,7 +209,7 @@ Note, currently the :similarity option has no effect when :use_lcs is false.
|
|
202
209
|
a = {x: [0, 1, 2]}
|
203
210
|
b = {x: [0, 2, 2, 3]}
|
204
211
|
|
205
|
-
diff =
|
212
|
+
diff = Hashdiff.diff(a, b, use_lcs: false)
|
206
213
|
diff.should == [["~", "x[1]", 1, 2], ["+", "x[3]", 3]]
|
207
214
|
```
|
208
215
|
|
@@ -214,7 +221,7 @@ It's possible to specify how the values of a key should be compared.
|
|
214
221
|
a = {a:'car', b:'boat', c:'plane'}
|
215
222
|
b = {a:'bus', b:'truck', c:' plan'}
|
216
223
|
|
217
|
-
diff =
|
224
|
+
diff = Hashdiff.diff(a, b) do |path, obj1, obj2|
|
218
225
|
case path
|
219
226
|
when /a|b|c/
|
220
227
|
obj1.length == obj2.length
|
@@ -230,7 +237,7 @@ The yielded params of the comparison block is `|path, obj1, obj2|`, in which pat
|
|
230
237
|
a = {a:'car', b:['boat', 'plane'] }
|
231
238
|
b = {a:'bus', b:['truck', ' plan'] }
|
232
239
|
|
233
|
-
diff =
|
240
|
+
diff = Hashdiff.diff(a, b) do |path, obj1, obj2|
|
234
241
|
case path
|
235
242
|
when 'b[*]'
|
236
243
|
obj1.length == obj2.length
|
@@ -252,14 +259,18 @@ An order difference alone between two arrays can create too many diffs to be use
|
|
252
259
|
a = {a:'car', b:['boat', 'plane'] }
|
253
260
|
b = {a:'car', b:['plane', 'boat'] }
|
254
261
|
|
255
|
-
|
262
|
+
Hashdiff.diff(a, b).should == [["+", "b[0]", "plane"], ["-", "b[2]", "plane"]]
|
256
263
|
|
257
264
|
b[:b].sort!
|
258
265
|
|
259
|
-
|
266
|
+
Hashdiff.diff(a, b).should == []
|
260
267
|
```
|
261
268
|
|
262
|
-
##
|
269
|
+
## Maintainers
|
263
270
|
|
264
|
-
|
271
|
+
- Krzysztof Rybka ([@krzysiek1507](https://github.com/krzysiek1507))
|
272
|
+
- Fengyun Liu ([@liufengyun](https://github.com/liufengyun))
|
273
|
+
|
274
|
+
## License
|
265
275
|
|
276
|
+
Hashdiff is distributed under the MIT-LICENSE.
|
data/Rakefile
CHANGED
@@ -1,13 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
|
+
|
5
|
+
require 'rubocop/rake_task'
|
2
6
|
|
3
7
|
require 'bundler'
|
4
8
|
Bundler::GemHelper.install_tasks
|
5
9
|
|
6
10
|
require 'rspec/core/rake_task'
|
7
11
|
|
8
|
-
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
|
14
|
+
task default: %w[spec rubocop]
|
9
15
|
|
10
16
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
11
|
-
spec.pattern =
|
17
|
+
spec.pattern = './spec/**/*_spec.rb'
|
12
18
|
end
|
13
|
-
|
data/changelog.md
CHANGED
@@ -1,5 +1,34 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## v1.0.1 2020-02-25
|
4
|
+
|
5
|
+
* Add indifferent option
|
6
|
+
|
7
|
+
## v1.0.0 2019-06-06
|
8
|
+
|
9
|
+
* Fix typo in readme (#72 @koic)
|
10
|
+
* Fix Rubocop offence (#73 @koic)
|
11
|
+
* Bumps version to v1.0.0 (#74 @jfelchner)
|
12
|
+
|
13
|
+
## v1.0.0.beta1 2019-06-06
|
14
|
+
|
15
|
+
* fix warnings in ci (#69 @y-yagi)
|
16
|
+
* drop warnings of the constant change (#70 @jfelchner)
|
17
|
+
|
18
|
+
## v0.4.0 2019-05-28
|
19
|
+
|
20
|
+
* refactoring (#56 #57 #59 #61 krzysiek1507)
|
21
|
+
* fix typo in README (#64 @pboling)
|
22
|
+
* change HashDiff to Hashdiff (#65 @jfelchner)
|
23
|
+
|
24
|
+
## v0.3.9 2019-04-22
|
25
|
+
|
26
|
+
* Performance tweak (thanks @krzysiek1507: #51 #52 #53)
|
27
|
+
|
28
|
+
## v0.3.8 2018-12-30
|
29
|
+
|
30
|
+
* Add Rubocop and drops Ruby 1.9 support #47
|
31
|
+
|
3
32
|
## v0.3.7 2017-10-08
|
4
33
|
|
5
34
|
* remove 1.8.7 support from gemspec #39
|
@@ -14,7 +43,7 @@
|
|
14
43
|
|
15
44
|
## v0.3.4 2017-05-01
|
16
45
|
|
17
|
-
* performance improvement of
|
46
|
+
* performance improvement of `#similar?` #31
|
18
47
|
|
19
48
|
## v0.3.2 2016-12-27
|
20
49
|
|
@@ -56,7 +85,7 @@
|
|
56
85
|
## v0.0.5 2012-7-1
|
57
86
|
|
58
87
|
* fix a bug in judging whehter two objects are similiar.
|
59
|
-
* add more spec test for
|
88
|
+
* add more spec test for `.best_diff`
|
60
89
|
|
61
90
|
## v0.0.4 2012-6-24
|
62
91
|
|
@@ -69,4 +98,3 @@ For example, `diff({a:2, c:[4, 5]}, {a:2}) will generate following output:
|
|
69
98
|
instead of following:
|
70
99
|
|
71
100
|
[['-', 'c[0]', 4], ['-', 'c[1]', 5], ['-', 'c', []]]
|
72
|
-
|
data/hashdiff.gemspec
CHANGED
@@ -1,25 +1,39 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH << File.expand_path('lib', __dir__)
|
2
4
|
require 'hashdiff/version'
|
3
5
|
|
4
6
|
Gem::Specification.new do |s|
|
5
|
-
s.name =
|
6
|
-
s.version =
|
7
|
+
s.name = 'hashdiff'
|
8
|
+
s.version = Hashdiff::VERSION
|
7
9
|
s.license = 'MIT'
|
8
|
-
s.summary =
|
9
|
-
s.description =
|
10
|
+
s.summary = ' Hashdiff is a diff lib to compute the smallest difference between two hashes. '
|
11
|
+
s.description = ' Hashdiff is a diff lib to compute the smallest difference between two hashes. '
|
10
12
|
|
11
13
|
s.files = `git ls-files`.split("\n")
|
12
14
|
s.test_files = `git ls-files -- Appraisals {spec}/*`.split("\n")
|
13
15
|
|
14
16
|
s.require_paths = ['lib']
|
15
|
-
s.required_ruby_version = Gem::Requirement.new(
|
17
|
+
s.required_ruby_version = Gem::Requirement.new('>= 2.0.0')
|
18
|
+
|
19
|
+
s.authors = ['Liu Fengyun']
|
20
|
+
s.email = ['liufengyunchina@gmail.com']
|
16
21
|
|
17
|
-
s.
|
18
|
-
s.email = ["liufengyunchina@gmail.com"]
|
22
|
+
s.homepage = 'https://github.com/liufengyun/hashdiff'
|
19
23
|
|
20
|
-
s.
|
24
|
+
s.add_development_dependency('bluecloth')
|
25
|
+
s.add_development_dependency('rspec', '~> 2.0')
|
26
|
+
s.add_development_dependency('rubocop', '~> 0.49.1') # last version that works with ruby 2.0
|
27
|
+
s.add_development_dependency('rubocop-rspec')
|
28
|
+
s.add_development_dependency('yard')
|
21
29
|
|
22
|
-
s.
|
23
|
-
|
24
|
-
|
30
|
+
if s.respond_to?(:metadata)
|
31
|
+
s.metadata = {
|
32
|
+
'bug_tracker_uri' => 'https://github.com/liufengyun/hashdiff/issues',
|
33
|
+
'changelog_uri' => 'https://github.com/liufengyun/hashdiff/blob/master/changelog.md',
|
34
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/hashdiff',
|
35
|
+
'homepage_uri' => 'https://github.com/liufengyun/hashdiff',
|
36
|
+
'source_code_uri' => 'https://github.com/liufengyun/hashdiff'
|
37
|
+
}
|
38
|
+
end
|
25
39
|
end
|
data/lib/hashdiff.rb
CHANGED
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hashdiff
|
4
|
+
# @private
|
5
|
+
# Used to compare hashes
|
6
|
+
class CompareHashes
|
7
|
+
class << self
|
8
|
+
def call(obj1, obj2, opts = {})
|
9
|
+
return [] if obj1.empty? && obj2.empty?
|
10
|
+
|
11
|
+
obj1_keys = obj1.keys
|
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
|
22
|
+
|
23
|
+
added_keys = (obj2_keys - obj1_keys).sort_by(&:to_s)
|
24
|
+
common_keys = (obj1_keys & obj2_keys).sort_by(&:to_s)
|
25
|
+
deleted_keys = (obj1_keys - obj2_keys).sort_by(&:to_s)
|
26
|
+
|
27
|
+
result = []
|
28
|
+
|
29
|
+
# add deleted properties
|
30
|
+
deleted_keys.each do |k|
|
31
|
+
k = opts[:indifferent] ? obj1_lookup[k] : k
|
32
|
+
change_key = Hashdiff.prefix_append_key(opts[:prefix], k, opts)
|
33
|
+
custom_result = Hashdiff.custom_compare(opts[:comparison], change_key, obj1[k], nil)
|
34
|
+
|
35
|
+
if custom_result
|
36
|
+
result.concat(custom_result)
|
37
|
+
else
|
38
|
+
result << ['-', change_key, obj1[k]]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# recursive comparison for common keys
|
43
|
+
common_keys.each do |k|
|
44
|
+
prefix = Hashdiff.prefix_append_key(opts[:prefix], k, opts)
|
45
|
+
|
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)))
|
49
|
+
end
|
50
|
+
|
51
|
+
# added properties
|
52
|
+
added_keys.each do |k|
|
53
|
+
change_key = Hashdiff.prefix_append_key(opts[:prefix], k, opts)
|
54
|
+
|
55
|
+
k = opts[:indifferent] ? obj2_lookup[k] : k
|
56
|
+
custom_result = Hashdiff.custom_compare(opts[:comparison], change_key, nil, obj2[k])
|
57
|
+
|
58
|
+
if custom_result
|
59
|
+
result.concat(custom_result)
|
60
|
+
else
|
61
|
+
result << ['+', change_key, obj2[k]]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
result
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|