Class: PaperTrailDiff::ActivityCollectionRouteUpdater

Inherits:
Object
  • Object
show all
Defined in:
lib/paper_trail_diff/activity_collection_route_updater.rb,
sig/generated/paper_trail_diff/activity_collection_route_updater.rbs

Overview

Replaces a collection event record along one explicit immutable snapshot route.

Instance Method Summary collapse

Constructor Details

#initialize(pool:, relationship:) ⇒ ActivityCollectionRouteUpdater

: (pool: SnapshotPool, relationship: ActivityRelationship) -> void

Parameters:



8
9
10
11
12
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 8

def initialize(pool:, relationship:)
  @pool = pool
  @relationship = relationship
  @record_updater = ActivityCollectionRecordUpdater.new(relationship)
end

Instance Method Details

#call(snapshot, change, depth: 0) ⇒ [ RecordSnapshot, bool ]

: (RecordSnapshot, ActivityCollectionRouteChange, ?depth: Integer) -> [RecordSnapshot, bool]

Parameters:

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 15

def call(snapshot, change, depth: 0) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  name, _reflection, _subtree, path = change.route.fetch(depth)
  association = snapshot.associations.fetch(name)
  transition = updated_records(association, snapshot, change, depth)
  records, before, after, membership_preserved, changed = transition
  return [snapshot, false] unless changed

  updated_association = @pool.association(
    path,
    association.transition_to(
      records,
      before: before,
      after: after,
      membership_preserved: membership_preserved
    )
  )
  updated_snapshot = replace_association(snapshot, name, updated_association)
  parent_path = depth.zero? ? '' : change.route.fetch(depth - 1).fetch(3)
  updated_snapshot = @pool.record(parent_path, updated_snapshot) unless parent_path.empty?
  [updated_snapshot, true]
end

#leaf_records(association, owner, change) ⇒ [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool ]

: (AssociationSnapshot, RecordSnapshot, ActivityCollectionRouteChange) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool]



57
58
59
60
61
62
63
64
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 57

def leaf_records(association, owner, change)
  reflection = change.route.last.fetch(1)
  child = @record_updater.event_child(association, change, reflection, owner)
  records, before, after, preserved = @record_updater.call(
    association, change.version, child
  )
  [records, before, after, preserved, !records.equal?(association.records)]
end

#nested_owner_position(association, reflection, change) ⇒ Integer?

: (AssociationSnapshot, untyped, ActivityCollectionRouteChange) -> Integer?

Parameters:

Returns:

  • (Integer, nil)


108
109
110
111
112
113
114
115
116
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 108

def nested_owner_position(association, reflection, change)
  membership_record = change.record || change.version.reify(dup: true)
  return unless membership_record
  return if membership_record.is_a?(ActivitySnapshotDelta) &&
            membership_record.relationship_changed?(reflection)

  owner_id = @relationship.owner_id(membership_record, reflection, state: :after)
  association.position_for_id(owner_id)
end

#recursive_records(association, change, depth) ⇒ [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool ]

: (AssociationSnapshot, ActivityCollectionRouteChange, Integer) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool]

Parameters:

Returns:



80
81
82
83
84
85
86
87
88
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 80

def recursive_records(association, change, depth)
  state = [nil, nil, false] #: [RecordSnapshot?, RecordSnapshot?, bool]
  records = association.records.map do |child|
    updated, child_changed = call(child, change, depth: depth + 1)
    state = recursive_transition(state, child, updated, child_changed)
    updated
  end.freeze
  [records, state.fetch(0), state.fetch(1), true, state.fetch(2)]
end

#recursive_transition(state, child, updated, child_changed) ⇒ [ RecordSnapshot?, RecordSnapshot?, bool ]

: ([RecordSnapshot?, RecordSnapshot?, bool], RecordSnapshot, RecordSnapshot, bool) -> [RecordSnapshot?, RecordSnapshot?, bool]

Parameters:

Returns:



91
92
93
94
95
96
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 91

def recursive_transition(state, child, updated, child_changed)
  return state unless child_changed
  return [nil, nil, true] if state.fetch(2)

  [child, updated, true]
end

#replace_association(snapshot, name, association) ⇒ RecordSnapshot

: (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot

Parameters:

Returns:



119
120
121
122
123
124
125
126
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 119

def replace_association(snapshot, name, association)
  RecordSnapshot.new(
    type: snapshot.type,
    id: snapshot.id,
    attributes: snapshot.attributes,
    associations: snapshot.associations.merge(name => association)
  )
end

#targeted_parent(association, change, depth) ⇒ [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]?

: (AssociationSnapshot, ActivityCollectionRouteChange, Integer) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]?

Parameters:

Returns:



67
68
69
70
71
72
73
74
75
76
77
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 67

def targeted_parent(association, change, depth)
  return unless depth == change.route.length - 2

  reflection = change.route.fetch(depth + 1).fetch(1)
  position = nested_owner_position(association, reflection, change)
  return unless position

  before = association.records.fetch(position)
  after, changed = call(before, change, depth: depth + 1)
  targeted_parent_replacement(association.records, position, before, after, changed)
end

#targeted_parent_replacement(records, position, before, after, changed) ⇒ [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]

: (Array, Integer, RecordSnapshot, RecordSnapshot, bool) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]

Parameters:

Returns:



99
100
101
102
103
104
105
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 99

def targeted_parent_replacement(records, position, before, after, changed)
  return [records, nil, nil, false] unless changed

  updated = records.dup
  updated[position] = after
  [updated.freeze, before, after, true]
end

#updated_records(association, owner, change, depth) ⇒ [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool ]

: (AssociationSnapshot, RecordSnapshot, ActivityCollectionRouteChange, Integer) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool]

Parameters:

Returns:



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/paper_trail_diff/activity_collection_route_updater.rb', line 44

def updated_records(association, owner, change, depth)
  return leaf_records(association, owner, change) if depth == change.route.length - 1

  targeted = targeted_parent(association, change, depth)
  if targeted
    records, before, after, changed = targeted
    return [records, before, after, true, changed]
  end

  recursive_records(association, change, depth)
end