Class: Odin::Diff::Differ

Inherits:
Object
  • Object
show all
Defined in:
lib/odin/diff/differ.rb

Instance Method Summary collapse

Instance Method Details

#compute_diff(doc_a, doc_b) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/odin/diff/differ.rb', line 8

def compute_diff(doc_a, doc_b)
  paths_a = Set.new(doc_a.paths)
  paths_b = Set.new(doc_b.paths)

  removed = []
  changed = []
  added = []

  # 1. Find removed: in A but not in B
  (paths_a - paths_b).sort.each do |path|
    removed << Types::DiffEntry.new(
      path: path,
      value: doc_a.get(path),
      modifiers: doc_a.modifiers_for(path)
    )
  end

  # 2. Find added: in B but not in A
  (paths_b - paths_a).sort.each do |path|
    added << Types::DiffEntry.new(
      path: path,
      value: doc_b.get(path),
      modifiers: doc_b.modifiers_for(path)
    )
  end

  # 3. Find changed: in both but different value or modifiers
  (paths_a & paths_b).sort.each do |path|
    val_a = doc_a.get(path)
    val_b = doc_b.get(path)
    mod_a = doc_a.modifiers_for(path)
    mod_b = doc_b.modifiers_for(path)

    unless values_equal?(val_a, val_b) && modifiers_equal?(mod_a, mod_b)
      changed << Types::DiffChange.new(
        path: path,
        old_value: val_a,
        new_value: val_b,
        old_modifiers: mod_a,
        new_modifiers: mod_b
      )
    end
  end

  # 4. Detect moves: removed value that appears as added value
  moved = detect_moves(removed, added)

  Types::OdinDiff.new(
    added: added,
    removed: removed,
    changed: changed,
    moved: moved
  )
end