Class: PaperTrailDiff::HistoricalSnapshotStore

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

Overview

Reconstructs and caches immutable historical snapshots for one adapter configuration.

Instance Method Summary collapse

Constructor Details

#initialize(tree:, traversal:, normalizer:, preparer:) ⇒ HistoricalSnapshotStore

: (tree: AssociationTree, traversal: AssociationTraversal, normalizer: SnapshotNormalizer, preparer: untyped) -> void

Parameters:



8
9
10
11
12
13
14
15
16
17
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 8

def initialize(tree:, traversal:, normalizer:, preparer:)
  @tree = tree
  @traversal = traversal
  @normalizer = normalizer
  @preparer = preparer
  @live_graph_collector = LiveGraphCollector.new(tree: tree, traversal: traversal)
  @snapshots = {} #: Hash[Array[untyped], RecordSnapshot?]
  @prepared_history = nil #: PreparedHistory?
  @prepared_histories = {} #: Hash[Array[untyped], PreparedHistory]
end

Instance Method Details

#association_reader(context_version, habtm_version:) ⇒ Object

: (untyped, habtm_version: untyped) -> untyped

Parameters:

  • (Object)
  • habtm_version: (Object)

Returns:

  • (Object)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 87

def association_reader(context_version, habtm_version:)
  fallback = HistoricalAssociationReifier.new(
    context_version,
    habtm_version: habtm_version
  )
  history = @prepared_histories[context_key(context_version)] || @prepared_history
  return fallback unless history

  PreparedAssociationReifier.new(
    history,
    context_version,
    habtm_boundary: habtm_version,
    fallback: fallback
  )
end

#batch_payload(records, root_versions) ⇒ Hash[Symbol, untyped]

: (Array, Array) -> Hash[Symbol, untyped]

Parameters:

  • (Array[untyped])
  • (Array[untyped])

Returns:

  • (Hash[Symbol, untyped])


128
129
130
131
132
133
134
135
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 128

def batch_payload(records, root_versions)
  {
    root_count: records.length,
    version_count: root_versions.length,
    model_type: records.first.class.base_class.name.to_s,
    batched: true
  }
end

#call(root_endpoint, context_endpoint) ⇒ RecordSnapshot?

: (untyped, untyped) -> RecordSnapshot?

Parameters:

  • (Object)
  • (Object)

Returns:



50
51
52
53
54
55
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 50

def call(root_endpoint, context_endpoint)
  key = snapshot_key(root_endpoint, context_endpoint)
  return @snapshots[key] if @snapshots.key?(key)

  @snapshots[key] = uncached(root_endpoint, context_endpoint)
end

#context_key(endpoint) ⇒ Array[untyped]

: (untyped) -> Array

Parameters:

  • (Object)

Returns:

  • (Array[untyped])


123
124
125
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 123

def context_key(endpoint)
  [endpoint.class.name, endpoint.id]
end

#custom(root_endpoint, context_endpoint, tree:, normalizer:) ⇒ RecordSnapshot?

: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?

Parameters:

Returns:



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 68

def custom(root_endpoint, context_endpoint, tree:, normalizer:)
  if Endpoint.version?(root_endpoint)
    return snapshot_from_version(
      root_endpoint,
      context_endpoint,
      tree: tree,
      normalizer: normalizer
    )
  end

  snapshot_from_live_root(
    root_endpoint,
    context_endpoint,
    tree: tree,
    normalizer: normalizer
  )
end

#normalize(record, context_version, tree:, normalizer:, habtm_version:) ⇒ RecordSnapshot?

: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, habtm_version: untyped) -> RecordSnapshot?

Parameters:

Returns:



181
182
183
184
185
186
187
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 181

def normalize(record, context_version, tree:, normalizer:, habtm_version:)
  reifier = association_reader(context_version, habtm_version: habtm_version)
  reflections = [] #: Array[untyped]
  reflections = @traversal.reflections_for(record.class, tree, path: '') if record
  reifier.reify(record, reflections) if record && !reflections.empty?
  normalizer.call(record, reifier: reifier)
end

#prepare(record, root_versions, start_at: root_versions.first.created_at, end_at: root_versions.last.created_at) ⇒ void

This method returns an undefined value.

: (untyped, Array, ?start_at: untyped, ?end_at: untyped) -> void

Parameters:

  • (Object)
  • (Array[untyped])
  • start_at: (Object) (defaults to: root_versions.first.created_at)
  • end_at: (Object) (defaults to: root_versions.last.created_at)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 20

def prepare(
  record,
  root_versions,
  start_at: root_versions.first.created_at,
  end_at: root_versions.last.created_at
)
  return if @tree.empty?
  # A batched preparation already covers these roots.
  return if root_versions.any? { |v| @prepared_histories.key?(context_key(v)) }

  @prepared_history = PreparedHistoryLoader.new(
    record,
    root_versions: root_versions,
    start_at: start_at,
    end_at: end_at,
    tree: @tree,
    traversal: @traversal
  ).call
end

#prepare_batch(records, root_versions) ⇒ void

This method returns an undefined value.

: (Array, Array) -> void

Parameters:

  • (Array[untyped])
  • (Array[untyped])


41
42
43
44
45
46
47
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 41

def prepare_batch(records, root_versions)
  return if @tree.empty? || records.empty? || root_versions.empty?

  Instrumentation.instrument('prepare_history', batch_payload(records, root_versions)) do
    register_batch(records, root_versions)
  end
end

#record_transition(version) ⇒ [ Hash[untyped, untyped], Hash[untyped, untyped] ]?

: (untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?

Parameters:

  • (Object)

Returns:

  • ([ Hash[untyped, untyped], Hash[untyped, untyped] ], nil)


104
105
106
107
108
109
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 104

def record_transition(version)
  history = @prepared_history
  return unless history

  history.record_transition(Endpoint.model_class(version), version.item_id, version)
end

#register_batch(records, root_versions) ⇒ void

This method returns an undefined value.

: (Array, Array) -> void

Parameters:

  • (Array[untyped])
  • (Array[untyped])


138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 138

def register_batch(records, root_versions)
  history = PreparedHistoryLoader.new(
    records.first,
    root_ids: records.map(&:id),
    root_versions: root_versions,
    start_at: root_versions.map(&:created_at).min,
    end_at: root_versions.map(&:created_at).max,
    tree: @tree,
    traversal: @traversal,
    live_records: @live_graph_collector.call(records)
  ).call
  root_versions.each { |version| @prepared_histories[context_key(version)] = history }
end

#snapshot_from_live_root(root_record, context_version, tree:, normalizer:) ⇒ RecordSnapshot?

: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?

Parameters:

Returns:



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 168

def snapshot_from_live_root(root_record, context_version, tree:, normalizer:)
  record = Endpoint.reload_record(root_record)
  @preparer.call(record.class, historical: true)
  normalize(
    record,
    context_version,
    tree: tree,
    normalizer: normalizer,
    habtm_version: context_version
  )
end

#snapshot_from_version(root_version, context_version, tree:, normalizer:) ⇒ RecordSnapshot?

: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?

Parameters:

Returns:



153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 153

def snapshot_from_version(root_version, context_version, tree:, normalizer:)
  model_class = Endpoint.model_class(root_version)
  @preparer.call(model_class, historical: true)
  @traversal.ensure_habtm_history!(model_class, root_version)
  record = root_version.reify(dup: true)
  normalize(
    record,
    context_version,
    tree: tree,
    normalizer: normalizer,
    habtm_version: root_version
  )
end

#snapshot_key(root_endpoint, context_endpoint) ⇒ Array[untyped]

: (untyped, untyped) -> Array

Parameters:

  • (Object)
  • (Object)

Returns:

  • (Array[untyped])


190
191
192
193
194
195
196
197
# File 'lib/paper_trail_diff/historical_snapshot_store.rb', line 190

def snapshot_key(root_endpoint, context_endpoint)
  [
    root_endpoint.class.name,
    root_endpoint.id,
    context_endpoint.class.name,
    context_endpoint.id
  ]
end

#uncached(root_endpoint, context_endpoint) ⇒ RecordSnapshot?

: (untyped, untyped) -> RecordSnapshot?

Parameters:

  • (Object)
  • (Object)

Returns:



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

def uncached(root_endpoint, context_endpoint)
  custom(
    root_endpoint,
    context_endpoint,
    tree: @tree,
    normalizer: @normalizer
  )
end