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 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.