Class: HashDeepDiff::Comparison

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/hash_deep_diff/comparison.rb

Overview

Representation of the recursive difference between two hashes main parts are

  • path - empty for original hashes, otherwise path to values being compared

  • left - basically left.dig(path), left value of two being compared

  • right - basically right.dig(path), right value of two being compared

Examples:

 - { one: :a } compared with { one: :b } does not have nesting so we compare keys and values
 - { one: { two: :a, zero: :z } } compared with { one: { two: :b, three: :c } } has nesting, so is represented as
   - { two: :a } compared with { two: :b, three: :c }, as there is no more nesting we compare keys and values
     and have the following comparisons
     { one: { two: :a } } compared to { one: { two: :b } } - value was changed
       i.e :a vas replaced with :b on path [:one, :two]
     { one: { zero: :z } } compared to NO_VALUE - value was deleted
       i.e :z vas replaced with NO_VALUE on path [:one, :zero]
     NO_VALUE compared to { one: { three: :c } } compared - value was added
       i.e NO_VALUE vas replaced with :c on path [:one, :three]
[
  #<HashDeepDiff::Delta:0x00007fc7bc8a6e58
    @change_key=#<HashDeepDiff::ChangeKey:0x00007fc7bc8a6d40 @path=[:one, :two]>,
    @value={:left=>:a, :right=>:b}>,
  #<HashDeepDiff::Delta:0x00007fc7bc8a6b60
    @change_key=#<HashDeepDiff::ChangeKey:0x00007fc7bc8a6a48 @path=[:one, :zero]>,
    @value={:left=>:z, :right=>HashDeepDiff::NO_VALUE}>,
  #<HashDeepDiff::Delta:0x00007fc7bc8a6930
    @change_key=#<HashDeepDiff::ChangeKey:0x00007fc7bc8a6818 @path=[:one, :three]>,
    @value={:left=>HashDeepDiff::NO_VALUE, :right=>:c}>]
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(original, changed, prefix = [], reporting_engine: Reports::Diff, delta_engine: Delta) ⇒ Comparison (private)

Returns a new instance of Comparison.

Parameters:

  • original (Object)

    original version

  • changed (Object)

    new version

  • prefix (Array) (defaults to: [])

    keys to fetch current comparison (not empty for nested comparisons)


76
77
78
79
80
81
82
# File 'lib/hash_deep_diff/comparison.rb', line 76

def initialize(original, changed, prefix = [], reporting_engine: Reports::Diff, delta_engine: Delta)
  @left = original
  @right = changed
  @path = prefix.to_ary
  @reporting_engine = reporting_engine
  @delta_engine = delta_engine
end

Instance Attribute Details

#delta_engineObject (readonly)

Returns the value of attribute delta_engine.


36
37
38
# File 'lib/hash_deep_diff/comparison.rb', line 36

def delta_engine
  @delta_engine
end

#pathObject (readonly, private)

Returns the value of attribute path.


71
72
73
# File 'lib/hash_deep_diff/comparison.rb', line 71

def path
  @path
end

#reporting_engineObject (readonly)

Returns the value of attribute reporting_engine.


36
37
38
# File 'lib/hash_deep_diff/comparison.rb', line 36

def reporting_engine
  @reporting_engine
end

Instance Method Details

#common_keysArray (private)

All keys from both original and compared objects

Returns:

  • (Array)

116
117
118
119
120
121
122
# File 'lib/hash_deep_diff/comparison.rb', line 116

def common_keys
  keys = []
  keys += left.keys if left.respond_to?(:keys)
  keys += right.keys if right.respond_to?(:keys)

  keys.uniq
end

#comparison_factoryHashDeepDiff::Factories::Comparison (private)


134
135
136
# File 'lib/hash_deep_diff/comparison.rb', line 134

def comparison_factory
  HashDeepDiff::Factories::Comparison.new(reporting_engine: reporting_engine)
end

#delta(key: NO_VALUE) ⇒ HashDeepDiff::Delta (private)

factory function

Returns:


126
127
128
129
130
131
# File 'lib/hash_deep_diff/comparison.rb', line 126

def delta(key: NO_VALUE)
  keys = path
  keys += [key] unless key == NO_VALUE

  HashDeepDiff::Delta.new(path: keys, value: { left: left(key), right: right(key) })
end

#deltasArray<HashDeepDiff::Delta> (private)

HashDeepDiff::Comparison broken down into array of Delta

Returns:


86
87
88
89
90
91
92
93
94
# File 'lib/hash_deep_diff/comparison.rb', line 86

def deltas
  return [delta] if common_keys.empty?

  common_keys.each_with_object([]) do |key, memo|
    next if values_equal?(key)

    memo.append(delta(key: key))
  end.flatten
end

#diffArray<HashDeepDiff::Delta>

Returns:


42
43
44
45
46
# File 'lib/hash_deep_diff/comparison.rb', line 42

def diff
  return [] if left == right

  deltas.flat_map { |new_delta| new_delta.simple? ? new_delta : inward_comparison(new_delta) }
end

#inward_comparison(complex_delta) ⇒ Array<HashDeepDiff::Delta> (private)

depending on circumstances will return necessary comparisons

Returns:


98
99
100
101
102
103
104
105
106
# File 'lib/hash_deep_diff/comparison.rb', line 98

def inward_comparison(complex_delta)
  if complex_delta.partial?
    complex_delta.placebo +
      comparison(delta: complex_delta, modifier: :addition).map(&:diff).flatten +
      comparison(delta: complex_delta, modifier: :deletion).map(&:diff).flatten
  else
    comparison(delta: complex_delta).map(&:diff).flatten
  end
end

#left(key = NO_VALUE) ⇒ Object

Parameters:

  • key (Object) (defaults to: NO_VALUE)

    the key which value we're currently comparing


49
50
51
52
53
54
55
# File 'lib/hash_deep_diff/comparison.rb', line 49

def left(key = NO_VALUE)
  return NO_VALUE if @left == NO_VALUE
  return @left if key == NO_VALUE
  return @left unless left.respond_to?(:to_hash)

  @left[key] || NO_VALUE
end

#report_engine_factoryHashDeepDiff::Reports::Base (private)


139
140
141
# File 'lib/hash_deep_diff/comparison.rb', line 139

def report_engine_factory
  reporting_engine.new(diff: diff)
end

#right(key = NO_VALUE) ⇒ Object

Parameters:

  • key (Object) (defaults to: NO_VALUE)

    the key which value we're currently comparing


58
59
60
61
62
63
64
# File 'lib/hash_deep_diff/comparison.rb', line 58

def right(key = NO_VALUE)
  return NO_VALUE if @right == NO_VALUE
  return @right if key == NO_VALUE
  return @right unless right.respond_to?(:to_hash)

  @right[key] || NO_VALUE
end

#values_equal?(key) ⇒ Bool (private)

Parameters:

  • key (Object)

    the key which value we're currently comparing

Returns:

  • (Bool)

110
111
112
# File 'lib/hash_deep_diff/comparison.rb', line 110

def values_equal?(key)
  right(key).instance_of?(left(key).class) && (right(key) == left(key))
end