hash_deep_diff 0.5.0 → 0.6.0

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
2
  SHA256:
3
- metadata.gz: 3aab07a4c397dbc84845d5f0faff052bbae89eb8be4bf24a5ed9df0d5129c3da
4
- data.tar.gz: 2ea89b301d808655625e0fa6a9c5028b9d194bba3c4dc54cf1f5c6859c59fc6f
3
+ metadata.gz: ddbaa8e8f12ba99330973c609c00ab710e9fa39b369797b80dd46f24aa6740e1
4
+ data.tar.gz: 6a5954a960ca0876cdb9e28f3e535be687de5596ed07be61581102b75b178ab4
5
5
  SHA512:
6
- metadata.gz: f0a05ee023dbbd4d8551b5065a57a65b645ca3b0a864eace0de91b10ec08da77b0a15df6422af0f5ce0afd4459ca141e227398f9560198f6d350963fac1a99f0
7
- data.tar.gz: 279185ca8464992a65f2fff626b6ee90f44ac7b7e98706e34443390ad24457961b642e5b2ebee10c4c8e3e5c72b7bfee454dd644f8f7ef68db5872c426137dc7
6
+ metadata.gz: af66a50e5a7eb848c96b757e8e37a4d767868de6fd96ebfd4f528085111e2fe1c9e39215b8514d534d33f94cfc4c024c5c2bba1813acad729fa906e18eee796a
7
+ data.tar.gz: 358e25298ee3c42ea469e44113fe62935ec8f564c4111c52e170bd25764d99cc4b71c42d154689ad2a9c54ff21f9359dad57cfbd450677853eb60655b90aecf4
data/Guardfile CHANGED
@@ -25,8 +25,8 @@ end
25
25
  guard :minitest do
26
26
  # with Minitest::Unit
27
27
  watch(%r{^test/(.*)/?test_(.*)\.rb$})
28
- # watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
29
- watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { 'test' }
28
+ watch(%r{^lib/hash_deep_diff/(.*/)?([^/]+)\.rb$}) { |m| "test/unit/#{m[1]}test_#{m[2]}.rb" }
29
+ # watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { 'test' }
30
30
  watch(%r{^test/test_helper\.rb$}) { 'test' }
31
31
  watch(%r{^test/support/.*$}) { 'test' }
32
32
  end
data/README.md CHANGED
@@ -36,8 +36,19 @@ HashDeepDiff::Comparison.new(left, right).report
36
36
  - left[a] = a
37
37
  + left[a] = b
38
38
  ```
39
- please see [Documentation](https://rdoc.info/gems/hash_deep_diff) for
40
- more info
39
+ please see [Documentation](https://rdoc.info/gems/hash_deep_diff/HashDeepDiff/Comparison) for
40
+ more information
41
+
42
+ ## Customization
43
+
44
+ You can implement and use your own reporting engines with the default `HashDeepDiff::Delta` objects as a source of the report. In order to do so implement your own version of the reporting engine (example can be found [here](https://github.com/bpohoriletz/hash_deep_diff/tree/main/lib/hash_deep_diff/reports)) and inject it into a `Comparison`
45
+
46
+ ```ruby
47
+ left = { a: :a }
48
+ right = { a: :b }
49
+
50
+ HashDeepDiff::Comparison.new(left, right, reporting_engine: CustomEngine).report
51
+ ```
41
52
 
42
53
  ## Contributing
43
54
 
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
23
23
 
24
24
  spec.metadata['homepage_uri'] = spec.homepage
25
+ spec.metadata['documentation_uri'] = 'https://rdoc.info/gems/hash_deep_diff'
25
26
  spec.metadata['source_code_uri'] = 'https://github.com/bpohoriletz/hash_deep_diff'
26
27
  spec.metadata['changelog_uri'] = 'https://github.com/bpohoriletz/hash_deep_diff/blob/main/CHANGELOG.md'
27
28
  spec.metadata['rubygems_mfa_required'] = 'true'
@@ -47,6 +48,7 @@ Gem::Specification.new do |spec|
47
48
  spec.add_development_dependency 'minitest', '~> 5.15.0'
48
49
  spec.add_development_dependency 'minitest-focus', '~> 1.3.1'
49
50
  spec.add_development_dependency 'minitest-reporters', '~> 1.5.0'
51
+ spec.add_development_dependency 'naught', '~> 1.1.0'
50
52
  spec.add_development_dependency 'rake', '~> 10.5.0'
51
53
  spec.add_development_dependency 'rubocop', '~> 1.26.1'
52
54
  spec.add_development_dependency 'rubocop-minitest', '~> 0.18.0'
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'delta'
3
+ require_relative 'factories/comparison'
4
4
 
5
5
  module HashDeepDiff
6
6
  # Representation of the recursive difference between two hashes
@@ -11,12 +11,12 @@ module HashDeepDiff
11
11
  #
12
12
  # Examples:
13
13
  # - { one: :a } compared with { one: :b } does not have nesting so we compare keys and values
14
- # - { one: { two: :a, zero: z } } compared with { one: { two: :b, three: :c } } has nesting, so is represented as
14
+ # - { one: { two: :a, zero: :z } } compared with { one: { two: :b, three: :c } } has nesting, so is represented as
15
15
  # - { two: :a } compared with { two: :b, three: :c }, as there is no more nesting we compare keys and values
16
16
  # and have the following comparisons
17
17
  # { one: { two: :a } } compared to { one: { two: :b } } - value was changed
18
18
  # i.e :a vas replaced with :b on path [:one, :two]
19
- # { one: { zero: z } } compared to NO_VALUE - value was deleted
19
+ # { one: { zero: :z } } compared to NO_VALUE - value was deleted
20
20
  # i.e :z vas replaced with NO_VALUE on path [:one, :zero]
21
21
  # NO_VALUE compared to { one: { three: :c } } compared - value was added
22
22
  # i.e NO_VALUE vas replaced with :c on path [:one, :three]
@@ -35,70 +35,116 @@ module HashDeepDiff
35
35
  # @value={:left=>HashDeepDiff::NO_VALUE, :right=>:c}>
36
36
  # ]
37
37
  class Comparison
38
+ extend Forwardable
38
39
  # @!attribute [r] left
39
40
  # @return [Hash] original version of the Hash
40
41
  # @!attribute [r] right
41
42
  # @return [Hash] Hash that the original is compared to
42
43
  # @!attribute [r] path
43
- # @return [Array<Object>] to a compared Hashes (is empty for top-level comparison)
44
- attr_reader :left, :right, :path
44
+ # @return [Array<Object>] subset of keys from original Hashes to fetch compared values
45
+ # (is empty for top-level comparison)
46
+ attr_reader :reporting_engine, :delta_engine
47
+
48
+ def_delegators :comparison_factory, :comparison
45
49
 
46
50
  # @return [String]
47
51
  def report
48
- diff.join("\n")
52
+ diff.map { |simple_delta| reporting_engine.new(delta: simple_delta).to_s }.join
49
53
  end
50
54
 
51
55
  # @return [Array<HashDeepDiff::Delta>]
52
56
  def diff
53
- comparison.flat_map do |delta|
54
- # if there are nested hashes we need to compare them furter
55
- # if no we return difference between values (HashDeepDiff::Delta)
56
- delta.complex? ? self.class.new(delta.left, delta.right, delta.path).diff : delta
57
- end
57
+ return [] if left == right
58
+
59
+ deltas.flat_map { |new_delta| new_delta.simple? ? new_delta : inward_comparison(new_delta) }
60
+ end
61
+
62
+ # @param [Object] key the key which value we're currently comparing
63
+ def left(key = NO_VALUE)
64
+ return NO_VALUE if @left == NO_VALUE
65
+ return @left if key == NO_VALUE
66
+
67
+ @left[key] || NO_VALUE
68
+ end
69
+
70
+ # @param [Object] key the key which value we're currently comparing
71
+ def right(key = NO_VALUE)
72
+ return NO_VALUE if @right == NO_VALUE
73
+ return @right if key == NO_VALUE
74
+
75
+ @right[key] || NO_VALUE
58
76
  end
59
77
 
60
78
  private
61
79
 
62
- # @param [Hash] left original version of the hash
63
- # @param [Hash] right new version of the hash
80
+ attr_reader :path
81
+
82
+ # @param [Object] original original version
83
+ # @param [Object] changed new version
64
84
  # @param [Array] prefix keys to fetch current comparison (not empty for nested comparisons)
65
- def initialize(left, right, prefix = [])
66
- @left = left.to_hash
67
- @right = right.to_hash
85
+ def initialize(original, changed, prefix = [], reporting_engine: Reports::Diff, delta_engine: Delta)
86
+ @left = original
87
+ @right = changed
68
88
  @path = prefix.to_ary
89
+ @reporting_engine = reporting_engine
90
+ @delta_engine = delta_engine
69
91
  end
70
92
 
93
+ # {Comparison} broken down into array of {Delta}
71
94
  # @return [Array<HashDeepDiff::Delta>]
72
- def comparison
95
+ def deltas
96
+ return [delta] if common_keys.empty?
97
+
73
98
  common_keys.each_with_object([]) do |key, memo|
74
99
  next if values_equal?(key)
75
100
 
76
- memo << Delta.new(path: path + [key], value: { left: value_left(key), right: value_right(key) })
101
+ memo << delta(key: key)
102
+ end
103
+ end
104
+
105
+ # depending on circumstances will return necessary comparisons
106
+ # @return [Array<HashDeepDiff::Delta>]
107
+ def inward_comparison(complex_delta)
108
+ if complex_delta.partial?
109
+ [
110
+ complex_delta.placebo,
111
+ comparison(delta: complex_delta, modifier: :right).diff,
112
+ comparison(delta: complex_delta, modifier: :left).diff
113
+ ].compact.flatten
114
+ # TOFIX add test an drop flatten
115
+ else
116
+ comparison(delta: complex_delta).diff
77
117
  end
78
118
  end
79
119
 
80
120
  # @param [Object] key the key which value we're currently comparing
81
121
  # @return [Bool]
82
122
  def values_equal?(key)
83
- value_right(key).instance_of?(value_left(key).class) && (value_right(key) == value_left(key))
123
+ right(key).instance_of?(left(key).class) && (right(key) == left(key))
84
124
  end
85
125
 
86
- # Original value
87
- # @param [Object] key the key which value we're currently comparing
88
- def value_left(key)
89
- left[key] || NO_VALUE
126
+ # All keys from both original and compared objects
127
+ # @return [Array]
128
+ def common_keys
129
+ keys = []
130
+ keys += left.keys if left.respond_to?(:keys)
131
+ keys += right.keys if right.respond_to?(:keys)
132
+
133
+ keys.uniq
90
134
  end
91
135
 
92
- # Value we compare to
93
- # @param [Object] key the key which value we're currently comparing
94
- def value_right(key)
95
- right[key] || NO_VALUE
136
+ # @return [HashDeepDiff::Factories::Comparison]
137
+ def comparison_factory
138
+ HashDeepDiff::Factories::Comparison.new(reporting_engine: reporting_engine)
96
139
  end
97
140
 
98
- # All keys from both original and compared objects
99
- # @return [Array]
100
- def common_keys
101
- (left.keys + right.keys).uniq
141
+ # factory function
142
+ # @return [HashDeepDiff::Delta]
143
+ def delta(key: NO_VALUE)
144
+ change_key = path
145
+ change_key += [key] unless key == NO_VALUE
146
+
147
+ HashDeepDiff::Delta.new(change_key: change_key, value: { left: left(key), right: right(key) })
102
148
  end
103
149
  end
104
150
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'acts_as_hash'
4
- require_relative 'report'
3
+ require 'forwardable'
5
4
 
6
5
  module HashDeepDiff
7
6
  # Representation of the diff of two values
@@ -10,74 +9,83 @@ module HashDeepDiff
10
9
  # - diff of { a: a } and { a: b } is { a: { left: a, right: b } }
11
10
  # - diff of {} and { a: b } is { a: { left: HashDeepDiff::NO_VALUE, right: b } }
12
11
  class Delta
13
- include ActsAsHash
12
+ extend Forwardable
14
13
 
15
- # Visual representation of additions and deletiond at given +path+
16
- # @return [String]
17
- def to_str
18
- [deletion, addition].compact.join("\n")
14
+ def_delegators :to_hash, :==, :each_with_object, :each_key, :[],
15
+ :to_a, :empty?, :keys
16
+ attr_reader :change_key
17
+
18
+ # an indication that nested Hash was deleted/added
19
+ # @return [HashDeepDiff::Delta, NilClass]
20
+ def placebo
21
+ return nil unless partial?
22
+
23
+ placebo = simple_left? ? { left: NO_VALUE, right: {} } : { left: {}, right: NO_VALUE }
24
+
25
+ self.class.new(change_key: change_key, value: placebo)
19
26
  end
20
27
 
21
- # Returns true if we have nested Hashes
28
+ # true if at least one of the values is a Hash
22
29
  # @return [Bool]
23
- def complex?
24
- left.respond_to?(:to_hash) && right.respond_to?(:to_hash)
30
+ def partial?
31
+ !composite? && !simple?
25
32
  end
26
33
 
27
- # Keys needed to fetch values that we're comparing
28
- # @return [Array]
29
- def path
30
- @prefix + [@delta.keys.first]
34
+ # true if both valus are Hashes
35
+ # @return [Bool]
36
+ def composite?
37
+ !simple_left? && !simple_right?
38
+ end
39
+
40
+ # true if none of the values is a Hash
41
+ # @return [Bool]
42
+ def simple?
43
+ simple_left? && simple_right?
31
44
  end
32
45
 
33
46
  # Original value
34
47
  def left
35
- @value[:left]
48
+ value[:left]
36
49
  end
37
50
 
38
51
  # Value we compare to
39
52
  def right
40
- @value[:right]
53
+ value[:right]
41
54
  end
42
55
 
43
- # See {#to_str}
44
- def to_s
45
- to_str
56
+ # see {#to_hash}
57
+ # @return [Hash]
58
+ def to_h
59
+ to_hash
60
+ end
61
+
62
+ # @return [Hash]
63
+ def to_hash
64
+ { change_key[-1] => value }
46
65
  end
47
66
 
48
67
  private
49
68
 
50
- # @param [Array, Object] path list of keys to fetch values we're comparing
69
+ attr_reader :value
70
+
71
+ # @param [Array] change_key list of keys to fetch values we're comparing
51
72
  # @param [Hash<(:left, :right), Object>] value +Hash+ object with two keys - :left and :right,
52
73
  # that represents compared original value (at :left) and value we compare to (at :right)
53
- def initialize(path:, value:)
54
- # TOFIX this may prohibit usage of hashes with Array keys
55
- # TOFIX extract path to a separate object
56
- if path.respond_to?(:to_ary)
57
- @delta = { path[-1] => value }
58
- @value = value
59
- @prefix = path[0..-2]
60
- else
61
- @delta = { path => value }
62
- @value = value
63
- @prefix = []
64
- end
74
+ def initialize(change_key:, value:)
75
+ @value = value
76
+ @change_key = change_key
65
77
  end
66
78
 
67
- # Visual representation of additions
68
- # @return [NillClass, String]
69
- def deletion
70
- return nil if left == NO_VALUE
71
-
72
- Report.new(path: path, value: left, mode: Report::Mode::DELETION)
79
+ # Returns true if left value has no nested Hashes
80
+ # @return [Bool]
81
+ def simple_left?
82
+ !left.respond_to?(:to_hash)
73
83
  end
74
84
 
75
- # Visual representation of deletions
76
- # @return [NillClass, String]
77
- def addition
78
- return nil if right == NO_VALUE
79
-
80
- Report.new(path: path, value: right)
85
+ # Returns true if right value has no nested Hashes
86
+ # @return [Bool]
87
+ def simple_right?
88
+ !right.respond_to?(:to_hash)
81
89
  end
82
90
  end
83
91
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module HashDeepDiff
6
+ # factories
7
+ module Factories
8
+ # Factory for {HashDeepDiff::Comparison}
9
+ class Comparison
10
+ extend Forwardable
11
+ def_delegators :delta, :left, :right, :change_key
12
+
13
+ # factory function
14
+ # @return [Comparison]
15
+ def comparison(delta:, modifier: nil)
16
+ @delta = delta
17
+
18
+ case modifier
19
+ when nil
20
+ full_compare
21
+ when :left
22
+ compare_left
23
+ when :right
24
+ compare_right
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :reporting_engine, :delta
31
+
32
+ def initialize(reporting_engine:)
33
+ @reporting_engine = reporting_engine
34
+ end
35
+
36
+ # compare two hashes
37
+ def full_compare
38
+ HashDeepDiff::Comparison.new(left, right, change_key,
39
+ delta_engine: delta.class,
40
+ reporting_engine: reporting_engine)
41
+ end
42
+
43
+ # compare Hash with nothing (deletion)
44
+ def compare_left
45
+ HashDeepDiff::Comparison.new(left, NO_VALUE, change_key,
46
+ delta_engine: delta.class,
47
+ reporting_engine: reporting_engine)
48
+ end
49
+
50
+ # compare nothing with Hash (addition)
51
+ def compare_right
52
+ HashDeepDiff::Comparison.new(NO_VALUE, right, change_key,
53
+ delta_engine: delta.class,
54
+ reporting_engine: reporting_engine)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HashDeepDiff
4
+ # Different reporting enjines for {Delta}
5
+ module Reports
6
+ # Abstract Class
7
+ class Base
8
+ # see {#to_str}
9
+ # @return [String]
10
+ def to_s
11
+ to_str
12
+ end
13
+
14
+ # A report on additions and deletions
15
+ # @return [String]
16
+ def to_str
17
+ original + replacement
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :old_val, :new_val, :change_key
23
+
24
+ # @param [Delta] delta diff to report
25
+ def initialize(delta:)
26
+ @change_key = delta.change_key.to_ary
27
+ @old_val = delta.left
28
+ @new_val = delta.right
29
+ end
30
+
31
+ # old value
32
+ def original
33
+ raise AbstractMethodError
34
+ end
35
+
36
+ # new value
37
+ def replacement
38
+ raise AbstractMethodError
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module HashDeepDiff
6
+ # Different reporting enjines for {Delta}
7
+ module Reports
8
+ # Visual representation of the {Delta} as diff
9
+ class Diff < Base
10
+ private
11
+
12
+ # old value
13
+ # @return [String]
14
+ def original
15
+ return '' if old_val == NO_VALUE
16
+
17
+ return "#{deletion}#{path} = #{old_val}\n"
18
+ end
19
+
20
+ # new value
21
+ # @return [String]
22
+ def replacement
23
+ return '' if new_val == NO_VALUE
24
+
25
+ return "#{addition}#{path} = #{new_val}\n"
26
+ end
27
+
28
+ # Visual representation of keys from compared objects needed to fetch the compared values
29
+ # @return [String]
30
+ def path
31
+ change_key.map { |key| "[#{key}]" }.join
32
+ end
33
+
34
+ # visual indication of addition
35
+ # @return [String]
36
+ def addition
37
+ '+left'
38
+ end
39
+
40
+ # visual indication of deletion
41
+ # @return [String]
42
+ def deletion
43
+ '-left'
44
+ end
45
+ end
46
+ end
47
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module HashDeepDiff
4
4
  # Version of a gem
5
- VERSION = '0.5.0'
5
+ VERSION = '0.6.0'
6
6
  end
@@ -1,10 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'hash_deep_diff/version'
4
+ require 'hash_deep_diff/reports/diff'
5
+ require 'hash_deep_diff/delta'
4
6
  require 'hash_deep_diff/comparison'
5
7
 
6
8
  # Global namespace
7
9
  module HashDeepDiff
8
10
  # value was not found
9
11
  NO_VALUE = Class.new(NilClass)
12
+ # Abstract method
13
+ AbstractMethodError = Class.new(NoMethodError)
14
+ # Any error
15
+ Error = Class.new(StandardError)
10
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash_deep_diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bohdan Pohorilets
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-18 00:00:00.000000000 Z
11
+ date: 2022-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 1.5.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: naught
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.1.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.1.0
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: rake
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -209,10 +223,11 @@ files:
209
223
  - bin/yri
210
224
  - hash_deep_diff.gemspec
211
225
  - lib/hash_deep_diff.rb
212
- - lib/hash_deep_diff/acts_as_hash.rb
213
226
  - lib/hash_deep_diff/comparison.rb
214
227
  - lib/hash_deep_diff/delta.rb
215
- - lib/hash_deep_diff/report.rb
228
+ - lib/hash_deep_diff/factories/comparison.rb
229
+ - lib/hash_deep_diff/reports/base.rb
230
+ - lib/hash_deep_diff/reports/diff.rb
216
231
  - lib/hash_deep_diff/version.rb
217
232
  homepage: https://github.com/bpohoriletz/hash_deep_diff
218
233
  licenses:
@@ -220,6 +235,7 @@ licenses:
220
235
  metadata:
221
236
  allowed_push_host: https://rubygems.org/
222
237
  homepage_uri: https://github.com/bpohoriletz/hash_deep_diff
238
+ documentation_uri: https://rdoc.info/gems/hash_deep_diff
223
239
  source_code_uri: https://github.com/bpohoriletz/hash_deep_diff
224
240
  changelog_uri: https://github.com/bpohoriletz/hash_deep_diff/blob/main/CHANGELOG.md
225
241
  rubygems_mfa_required: 'true'
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'forwardable'
4
-
5
- module HashDeepDiff
6
- # This module includes behavior that is needed to use instances of Delta instead of Hash
7
- # in this gem
8
- module ActsAsHash
9
- # @param [Object] base a hook that is invoked when module is included in a class
10
- def self.included(base)
11
- base.extend Forwardable
12
- base.def_delegators :@delta, :==, :each_with_object, :each_key, :[],
13
- :to_a, :empty?, :keys
14
- base.include InstanceMethods
15
- end
16
-
17
- # We assume that the class will initialize instance variable +@delta+ that will return
18
- # a representation of an instance of a class as a +Hash+ object
19
- module InstanceMethods
20
- # a +Hash+ representation of an object
21
- def to_h
22
- to_hash
23
- end
24
-
25
- # a +Hash+ representation of an object
26
- def to_hash
27
- @delta
28
- end
29
- end
30
- end
31
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module HashDeepDiff
4
- # Visual representation of the difference between two values
5
- class Report
6
- # We have two cases
7
- # * added - when value on the left is missing
8
- # * deleted - when the value on the right is missing
9
- module Mode
10
- # for additions
11
- ADDITION = '+left'
12
- # for deletions
13
- DELETION = '-left'
14
- end
15
-
16
- # A report with all additions and deletions
17
- # @return [String]
18
- def to_str
19
- if @value.respond_to?(:to_hash) && !@value.empty?
20
- [@mode, diff_prefix, ' = ', "{}\n"].join +
21
- @value.keys.map do |key|
22
- Report.new(path: @path + [key], value: @value[key], mode: @mode)
23
- end.join("\n")
24
- else
25
- [@mode, diff_prefix, ' = ', @value.to_s].join
26
- end
27
- end
28
-
29
- # A report with all additions and deletions
30
- # @return [String]
31
- def to_s
32
- to_str
33
- end
34
-
35
- private
36
-
37
- # @param [Array] path Keys from compared objects to fetch the compared values
38
- # @param [Object] value value from a compared object at +@path+
39
- # @param [Mode::ADDITION, Mode::DELETION] mode
40
- def initialize(path:, value:, mode: Mode::ADDITION)
41
- @path = path.to_ary
42
- @value = value
43
- @mode = mode
44
- end
45
-
46
- # Visual representation of keys from compared objects needed to fetch the compared values
47
- # @return [String]
48
- def diff_prefix
49
- # TOFIX poor naming
50
- @path.map { |key| "[#{key}]" }.join
51
- end
52
- end
53
- end