Module: Snappier::Changes

Defined in:
lib/snappier/changes.rb

Class Method Summary collapse

Class Method Details

.append_changes(changes, previous_state, current_state, path = []) ⇒ Object



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
# File 'lib/snappier/changes.rb', line 9

def self.append_changes(changes, previous_state, current_state, path = [])
  previous_state ||= {}
  current_state ||= {}
  keys = Set.new(previous_state.keys + current_state.keys)

  keys.each do |key|
    previous_value = previous_state[key]
    current_value = current_state[key]

    if previous_value.is_a?(Array) || current_value.is_a?(Array)
      append_changes_for_collections(changes, previous_value, current_value, path + [key])
      next
    end

    if previous_value.is_a?(Hash) || current_value.is_a?(Hash)
      previous_id = (previous_value || {}).delete("id")
      current_id = (current_value || {}).delete("id")

      if previous_id || current_id
        if previous_id == current_id
          append_changes(changes, previous_value, current_value, path + [key, previous_id])
        else
          append_changes(changes, previous_value, {}, path + [key, previous_id])
          append_changes(changes, {}, current_value, path + [key, current_id])
        end
      else
        append_changes(changes, previous_value, current_value, path + [key])
      end

      next
    end

    next if previous_value == current_value

    changes[path + [key]] = [previous_value, current_value]
  end
end

.append_changes_for_collections(changes, previous_collection, current_collection, path) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/snappier/changes.rb', line 47

def self.append_changes_for_collections(changes, previous_collection, current_collection, path)
  ids = ids_for_collections(previous_collection, current_collection)

  if ids.empty?
    changes[path] = [previous_collection, current_collection] unless previous_collection == current_collection
    return
  end

  ids.each do |id|
    previous_value = (previous_collection || []).find { |r| r["id"] == id } || {}
    current_value = (current_collection || []).find { |r| r["id"] == id } || {}
    previous_value&.delete("id")
    current_value&.delete("id")

    append_changes(changes, previous_value, current_value, path + [id])
  end
end

.between(previous_state, current_state) ⇒ Object



5
6
7
# File 'lib/snappier/changes.rb', line 5

def self.between(previous_state, current_state)
  {}.tap { |changes| append_changes(changes, previous_state, current_state) }
end

.ids_for_collections(*collections) ⇒ Object



65
66
67
68
69
70
71
# File 'lib/snappier/changes.rb', line 65

def self.ids_for_collections(*collections)
  Set.new.tap do |ids|
    collections.each do |collection|
      (collection || []).each { |e| ids << e["id"] if e["id"] }
    end
  end
end