paper_trail_diff 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +144 -0
- data/QUICKSTART.md +149 -79
- data/README.md +179 -1367
- data/docs/architecture.md +88 -0
- data/docs/performance.md +309 -0
- data/docs/reference.md +977 -0
- data/docs/testing.md +146 -0
- data/lib/paper_trail_diff/activity_belongs_to_event_applier.rb +2 -12
- data/lib/paper_trail_diff/activity_boundary.rb +20 -8
- data/lib/paper_trail_diff/activity_child_candidate_loader.rb +29 -0
- data/lib/paper_trail_diff/activity_collection_event_applier.rb +10 -7
- data/lib/paper_trail_diff/activity_collection_route_updater.rb +1 -11
- data/lib/paper_trail_diff/activity_event_record_normalizer.rb +4 -0
- data/lib/paper_trail_diff/activity_event_record_resolver.rb +66 -6
- data/lib/paper_trail_diff/activity_event_snapshot_refresher.rb +6 -4
- data/lib/paper_trail_diff/activity_grouping.rb +12 -0
- data/lib/paper_trail_diff/activity_history.rb +9 -3
- data/lib/paper_trail_diff/activity_relationship.rb +2 -0
- data/lib/paper_trail_diff/activity_root_snapshot_refresher.rb +1 -0
- data/lib/paper_trail_diff/activity_snapshot_sequence.rb +9 -2
- data/lib/paper_trail_diff/activity_timeline_builder.rb +39 -35
- data/lib/paper_trail_diff/activity_version_collector.rb +27 -18
- data/lib/paper_trail_diff/analysis.rb +9 -4
- data/lib/paper_trail_diff/analysis_batch.rb +28 -7
- data/lib/paper_trail_diff/association_traversal.rb +23 -0
- data/lib/paper_trail_diff/batch_boundary_resolver.rb +18 -26
- data/lib/paper_trail_diff/batch_safety.rb +55 -0
- data/lib/paper_trail_diff/batched_root_analyzer.rb +14 -5
- data/lib/paper_trail_diff/batched_root_versions.rb +9 -37
- data/lib/paper_trail_diff/branch_snapshot_refresher.rb +7 -8
- data/lib/paper_trail_diff/deleted_analysis_batch.rb +93 -0
- data/lib/paper_trail_diff/direct_record_state_loader.rb +81 -0
- data/lib/paper_trail_diff/endpoint.rb +10 -0
- data/lib/paper_trail_diff/engine.rb +4 -2
- data/lib/paper_trail_diff/errors.rb +9 -0
- data/lib/paper_trail_diff/historical_association_reifier.rb +26 -1
- data/lib/paper_trail_diff/historical_filter.rb +181 -0
- data/lib/paper_trail_diff/historical_snapshot_store.rb +51 -35
- data/lib/paper_trail_diff/instrumentation.rb +2 -2
- data/lib/paper_trail_diff/nested_comparator.rb +59 -24
- data/lib/paper_trail_diff/paper_trail_adapter.rb +109 -55
- data/lib/paper_trail_diff/prepared_activity_index.rb +121 -0
- data/lib/paper_trail_diff/prepared_edge_loader.rb +11 -11
- data/lib/paper_trail_diff/prepared_history.rb +21 -30
- data/lib/paper_trail_diff/prepared_history_loader.rb +14 -2
- data/lib/paper_trail_diff/prepared_record_index.rb +102 -29
- data/lib/paper_trail_diff/prepared_snapshot_builder.rb +64 -0
- data/lib/paper_trail_diff/prepared_state_association_reader.rb +77 -0
- data/lib/paper_trail_diff/root_version_plan.rb +25 -2
- data/lib/paper_trail_diff/root_version_selection.rb +16 -5
- data/lib/paper_trail_diff/scoped_analysis.rb +17 -2
- data/lib/paper_trail_diff/scoped_analysis_builder.rb +47 -0
- data/lib/paper_trail_diff/scoped_root_selection.rb +106 -13
- data/lib/paper_trail_diff/snapshot.rb +9 -0
- data/lib/paper_trail_diff/snapshot_normalizer.rb +41 -2
- data/lib/paper_trail_diff/step.rb +10 -5
- data/lib/paper_trail_diff/stored_time_precision.rb +68 -0
- data/lib/paper_trail_diff/support.rb +13 -3
- data/lib/paper_trail_diff/time_activity_timeline_builder.rb +19 -7
- data/lib/paper_trail_diff/time_range.rb +22 -2
- data/lib/paper_trail_diff/time_version_range.rb +1 -15
- data/lib/paper_trail_diff/timeline_builder.rb +5 -4
- data/lib/paper_trail_diff/timeline_range.rb +25 -43
- data/lib/paper_trail_diff/timeline_snapshot_provider.rb +13 -2
- data/lib/paper_trail_diff/traversal.rb +1 -1
- data/lib/paper_trail_diff/value_objects.rb +66 -0
- data/lib/paper_trail_diff/version.rb +1 -1
- data/lib/paper_trail_diff/version_association_candidate_scope.rb +1 -1
- data/lib/paper_trail_diff/version_boundary.rb +48 -0
- data/lib/paper_trail_diff/version_query.rb +33 -0
- data/lib/paper_trail_diff/version_range.rb +10 -38
- data/lib/paper_trail_diff.rb +81 -43
- data/sig/generated/paper_trail_diff/activity_belongs_to_event_applier.rbs +0 -3
- data/sig/generated/paper_trail_diff/activity_boundary.rbs +9 -4
- data/sig/generated/paper_trail_diff/activity_child_candidate_loader.rbs +11 -0
- data/sig/generated/paper_trail_diff/activity_collection_event_applier.rbs +4 -4
- data/sig/generated/paper_trail_diff/activity_collection_route_updater.rbs +0 -3
- data/sig/generated/paper_trail_diff/activity_event_record_resolver.rbs +19 -3
- data/sig/generated/paper_trail_diff/activity_event_snapshot_refresher.rbs +2 -2
- data/sig/generated/paper_trail_diff/activity_grouping.rbs +3 -0
- data/sig/generated/paper_trail_diff/activity_history.rbs +6 -2
- data/sig/generated/paper_trail_diff/activity_snapshot_sequence.rbs +7 -2
- data/sig/generated/paper_trail_diff/activity_timeline_builder.rbs +8 -3
- data/sig/generated/paper_trail_diff/activity_version_collector.rbs +4 -8
- data/sig/generated/paper_trail_diff/analysis.rbs +2 -2
- data/sig/generated/paper_trail_diff/analysis_batch.rbs +14 -3
- data/sig/generated/paper_trail_diff/association_traversal.rbs +11 -0
- data/sig/generated/paper_trail_diff/batch_boundary_resolver.rbs +7 -10
- data/sig/generated/paper_trail_diff/batch_safety.rbs +24 -0
- data/sig/generated/paper_trail_diff/batched_root_analyzer.rbs +8 -2
- data/sig/generated/paper_trail_diff/batched_root_versions.rbs +4 -16
- data/sig/generated/paper_trail_diff/branch_snapshot_refresher.rbs +2 -2
- data/sig/generated/paper_trail_diff/deleted_analysis_batch.rbs +44 -0
- data/sig/generated/paper_trail_diff/direct_record_state_loader.rbs +42 -0
- data/sig/generated/paper_trail_diff/endpoint.rbs +5 -0
- data/sig/generated/paper_trail_diff/engine.rbs +4 -2
- data/sig/generated/paper_trail_diff/errors.rbs +12 -0
- data/sig/generated/paper_trail_diff/historical_association_reifier.rbs +8 -0
- data/sig/generated/paper_trail_diff/historical_filter.rbs +75 -0
- data/sig/generated/paper_trail_diff/historical_snapshot_store.rbs +17 -4
- data/sig/generated/paper_trail_diff/nested_comparator.rbs +31 -18
- data/sig/generated/paper_trail_diff/paper_trail_adapter.rbs +36 -15
- data/sig/generated/paper_trail_diff/prepared_activity_index.rbs +56 -0
- data/sig/generated/paper_trail_diff/prepared_edge_loader.rbs +3 -3
- data/sig/generated/paper_trail_diff/prepared_history.rbs +12 -14
- data/sig/generated/paper_trail_diff/prepared_history_loader.rbs +2 -0
- data/sig/generated/paper_trail_diff/prepared_record_index.rbs +43 -6
- data/sig/generated/paper_trail_diff/prepared_snapshot_builder.rbs +24 -0
- data/sig/generated/paper_trail_diff/prepared_state_association_reader.rbs +33 -0
- data/sig/generated/paper_trail_diff/root_version_plan.rbs +15 -2
- data/sig/generated/paper_trail_diff/root_version_selection.rbs +8 -1
- data/sig/generated/paper_trail_diff/scoped_analysis.rbs +14 -2
- data/sig/generated/paper_trail_diff/scoped_analysis_builder.rbs +22 -0
- data/sig/generated/paper_trail_diff/scoped_root_selection.rbs +46 -6
- data/sig/generated/paper_trail_diff/snapshot.rbs +4 -0
- data/sig/generated/paper_trail_diff/snapshot_normalizer.rbs +13 -0
- data/sig/generated/paper_trail_diff/step.rbs +8 -2
- data/sig/generated/paper_trail_diff/stored_time_precision.rbs +36 -0
- data/sig/generated/paper_trail_diff/support.rbs +7 -0
- data/sig/generated/paper_trail_diff/time_activity_timeline_builder.rbs +7 -2
- data/sig/generated/paper_trail_diff/time_range.rbs +9 -0
- data/sig/generated/paper_trail_diff/time_version_range.rbs +0 -6
- data/sig/generated/paper_trail_diff/timeline_builder.rbs +2 -2
- data/sig/generated/paper_trail_diff/timeline_range.rbs +10 -14
- data/sig/generated/paper_trail_diff/timeline_snapshot_provider.rbs +2 -0
- data/sig/generated/paper_trail_diff/value_objects.rbs +45 -0
- data/sig/generated/paper_trail_diff/version_boundary.rbs +23 -0
- data/sig/generated/paper_trail_diff/version_query.rbs +15 -0
- data/sig/generated/paper_trail_diff/version_range.rbs +5 -14
- data/sig/generated/paper_trail_diff.rbs +37 -27
- metadata +31 -5
data/lib/paper_trail_diff.rb
CHANGED
|
@@ -5,11 +5,15 @@ require 'paper_trail'
|
|
|
5
5
|
|
|
6
6
|
require_relative 'paper_trail_diff/version'
|
|
7
7
|
require_relative 'paper_trail_diff/support'
|
|
8
|
+
require_relative 'paper_trail_diff/version_query'
|
|
9
|
+
require_relative 'paper_trail_diff/stored_time_precision'
|
|
10
|
+
require_relative 'paper_trail_diff/version_boundary'
|
|
8
11
|
require_relative 'paper_trail_diff/instrumentation'
|
|
9
12
|
require_relative 'paper_trail_diff/errors'
|
|
10
13
|
require_relative 'paper_trail_diff/configuration'
|
|
11
14
|
require_relative 'paper_trail_diff/endpoint'
|
|
12
15
|
require_relative 'paper_trail_diff/association_traversal'
|
|
16
|
+
require_relative 'paper_trail_diff/batch_safety'
|
|
13
17
|
require_relative 'paper_trail_diff/traversal_preparer'
|
|
14
18
|
require_relative 'paper_trail_diff/association_discovery'
|
|
15
19
|
require_relative 'paper_trail_diff/diagnostics'
|
|
@@ -28,6 +32,10 @@ require_relative 'paper_trail_diff/nested_comparator'
|
|
|
28
32
|
require_relative 'paper_trail_diff/engine'
|
|
29
33
|
require_relative 'paper_trail_diff/historical_association_reifier'
|
|
30
34
|
require_relative 'paper_trail_diff/prepared_record_index'
|
|
35
|
+
require_relative 'paper_trail_diff/direct_record_state_loader'
|
|
36
|
+
require_relative 'paper_trail_diff/prepared_state_association_reader'
|
|
37
|
+
require_relative 'paper_trail_diff/prepared_snapshot_builder'
|
|
38
|
+
require_relative 'paper_trail_diff/prepared_activity_index'
|
|
31
39
|
require_relative 'paper_trail_diff/prepared_history'
|
|
32
40
|
require_relative 'paper_trail_diff/version_association_candidate_scope'
|
|
33
41
|
require_relative 'paper_trail_diff/prepared_edge_loader'
|
|
@@ -66,8 +74,11 @@ require_relative 'paper_trail_diff/step'
|
|
|
66
74
|
require_relative 'paper_trail_diff/analysis'
|
|
67
75
|
require_relative 'paper_trail_diff/activity_root_steps'
|
|
68
76
|
require_relative 'paper_trail_diff/analysis_batch'
|
|
77
|
+
require_relative 'paper_trail_diff/deleted_analysis_batch'
|
|
69
78
|
require_relative 'paper_trail_diff/scoped_analysis'
|
|
79
|
+
require_relative 'paper_trail_diff/historical_filter'
|
|
70
80
|
require_relative 'paper_trail_diff/scoped_root_selection'
|
|
81
|
+
require_relative 'paper_trail_diff/scoped_analysis_builder'
|
|
71
82
|
require_relative 'paper_trail_diff/batched_root_analyzer'
|
|
72
83
|
require_relative 'paper_trail_diff/version_range'
|
|
73
84
|
require_relative 'paper_trail_diff/version_sequence_diagnostics'
|
|
@@ -92,10 +103,16 @@ require_relative 'paper_trail_diff/paper_trail_adapter'
|
|
|
92
103
|
# type attribute_changes = Hash[String, ValueChange]
|
|
93
104
|
# type association_diff = ToOneAssociationDiff | CollectionAssociationDiff
|
|
94
105
|
# type association_diffs = Hash[String, association_diff]
|
|
106
|
+
# type nested_change = ValueChange | ArrayChange
|
|
107
|
+
# type nested_changes = Hash[Array[String], nested_change]
|
|
95
108
|
# type association_snapshots = Hash[String, AssociationSnapshot]
|
|
96
109
|
# type identity = Array[untyped]
|
|
97
110
|
# type comparison_input = Hash[String | Symbol, untyped]
|
|
98
111
|
# type comparison_results = Hash[identity, Diff]
|
|
112
|
+
# type report_options = {
|
|
113
|
+
# within: untyped, activity: bool, version_scope: untyped,
|
|
114
|
+
# close_on: Symbol?, snapshots: bool, group: Symbol?
|
|
115
|
+
# }
|
|
99
116
|
# type ignore_option = Array[String | Symbol] | Hash[String | Symbol, untyped]
|
|
100
117
|
# type reference_key = :type | :id | "type" | "id"
|
|
101
118
|
# type traversal_context = :change | :included_state
|
|
@@ -115,7 +132,7 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
115
132
|
has_and_belongs_to_many
|
|
116
133
|
].freeze
|
|
117
134
|
|
|
118
|
-
class << self
|
|
135
|
+
class << self # rubocop:disable Metrics/ClassLength
|
|
119
136
|
# Compares net state between explicit PaperTrail-version or current-record endpoints.
|
|
120
137
|
#: (untyped, untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?reload_live_endpoints: bool) -> Diff
|
|
121
138
|
def compare(
|
|
@@ -136,21 +153,23 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
136
153
|
end
|
|
137
154
|
|
|
138
155
|
# Compares many independent endpoint pairs while batching current-record loading.
|
|
139
|
-
#: (Array[comparison_input], ?associations: Array[String | Symbol], ?ignore: ignore_option, ?reload_live_endpoints: bool) -> comparison_results
|
|
156
|
+
#: (Array[comparison_input], ?associations: Array[String | Symbol], ?ignore: ignore_option, ?reload_live_endpoints: bool, ?allow_expensive: bool) -> comparison_results
|
|
140
157
|
def compare_many(
|
|
141
158
|
comparisons,
|
|
142
159
|
associations: [],
|
|
143
160
|
ignore: DEFAULT_IGNORED_ATTRIBUTES,
|
|
144
|
-
reload_live_endpoints: true
|
|
161
|
+
reload_live_endpoints: true,
|
|
162
|
+
allow_expensive: false
|
|
145
163
|
)
|
|
146
164
|
PaperTrailAdapter.new(
|
|
147
165
|
associations: associations,
|
|
148
166
|
ignore: ignore,
|
|
149
|
-
reload_live_endpoints: reload_live_endpoints
|
|
167
|
+
reload_live_endpoints: reload_live_endpoints, allow_expensive: allow_expensive
|
|
150
168
|
).compare_many(comparisons)
|
|
151
169
|
end
|
|
152
170
|
|
|
153
|
-
# Compares every adjacent reconstructed state in an inclusive version range
|
|
171
|
+
# Compares every adjacent reconstructed state in an inclusive version range,
|
|
172
|
+
# by default the record's whole history through its current state.
|
|
154
173
|
#: (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?version_scope: untyped, ?close_on: Symbol?) -> Array[Step]
|
|
155
174
|
def timeline( # rubocop:disable Metrics/ParameterLists
|
|
156
175
|
record,
|
|
@@ -173,9 +192,10 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
173
192
|
end
|
|
174
193
|
|
|
175
194
|
# Compares adjacent root and selected-descendant activity boundaries.
|
|
176
|
-
# `reload_live_endpoints:` applies
|
|
177
|
-
#
|
|
178
|
-
|
|
195
|
+
# `reload_live_endpoints:` applies whenever the range ends at the current
|
|
196
|
+
# record: an explicit `to:` record, the default range, or a window with no
|
|
197
|
+
# later version.
|
|
198
|
+
#: (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?reload_live_endpoints: bool, ?version_scope: untyped, ?close_on: Symbol?, ?snapshots: bool, ?group: Symbol?) -> Array[ActivityStep]
|
|
179
199
|
def activity_timeline( # rubocop:disable Metrics/ParameterLists
|
|
180
200
|
record,
|
|
181
201
|
from: nil,
|
|
@@ -233,47 +253,36 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
233
253
|
)
|
|
234
254
|
end
|
|
235
255
|
|
|
236
|
-
# Analyzes
|
|
237
|
-
# history once for the batch instead of once per record
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
#
|
|
241
|
-
|
|
242
|
-
# you from a relation, which returns a `ScopedAnalysis` -- the same Hash,
|
|
243
|
-
# plus the roots the relation could not reach. See `analyze_scope` for why
|
|
244
|
-
# that second collection exists.
|
|
245
|
-
#: (?Array[untyped]?, ?scope: untyped, ?limit: Integer?, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool, ?version_scope: untyped, ?close_on: Symbol?) -> (Hash[identity, Analysis] | ScopedAnalysis)
|
|
256
|
+
# Analyzes an array of records over one shared range, preparing their
|
|
257
|
+
# selected history once for the batch instead of once per record, and
|
|
258
|
+
# returns a frozen Hash keyed by identity. Roots with nothing to report in
|
|
259
|
+
# the window return an empty `Analysis`. To let a relation choose the
|
|
260
|
+
# records, use `analyze_scope`.
|
|
261
|
+
#: (Array[untyped], ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool, ?version_scope: untyped, ?close_on: Symbol?, ?snapshots: bool, ?group: Symbol?, ?allow_expensive: bool) -> Hash[identity, Analysis]
|
|
246
262
|
def analyze_many( # rubocop:disable Metrics/ParameterLists
|
|
247
|
-
records
|
|
248
|
-
scope: nil,
|
|
249
|
-
limit: nil,
|
|
263
|
+
records,
|
|
250
264
|
within: nil,
|
|
251
265
|
associations: [],
|
|
252
266
|
ignore: DEFAULT_IGNORED_ATTRIBUTES,
|
|
253
267
|
activity: false,
|
|
254
268
|
version_scope: nil,
|
|
255
|
-
close_on: nil
|
|
269
|
+
close_on: nil,
|
|
270
|
+
snapshots: false,
|
|
271
|
+
group: nil,
|
|
272
|
+
allow_expensive: false
|
|
256
273
|
)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return adapter.analyze_scope(scope, limit: limit, within: within, activity: activity,
|
|
262
|
-
version_scope: version_scope, close_on: close_on)
|
|
263
|
-
end
|
|
264
|
-
raise ConfigurationError, 'pass records or scope:' if records.nil?
|
|
265
|
-
|
|
266
|
-
adapter.analyze_many(records, within: within, activity: activity,
|
|
267
|
-
version_scope: version_scope, close_on: close_on)
|
|
274
|
+
PaperTrailAdapter.new(
|
|
275
|
+
associations: associations, ignore: ignore, allow_expensive: allow_expensive
|
|
276
|
+
).analyze_many(records, within: within, activity: activity, version_scope: version_scope,
|
|
277
|
+
close_on: close_on, snapshots: snapshots, group: group)
|
|
268
278
|
end
|
|
269
279
|
|
|
270
280
|
# Analyzes every root the relation reaches whose history moved inside the
|
|
271
|
-
# window
|
|
272
|
-
# caller rediscover them.
|
|
281
|
+
# window. Joined duplicates are read in bounded pages and analyzed once.
|
|
273
282
|
#
|
|
274
283
|
# `limit:` is required and exceeding it raises. Selection moves into the gem
|
|
275
|
-
# here
|
|
276
|
-
#
|
|
284
|
+
# here. The relation's own limit/offset select the live page; this separate
|
|
285
|
+
# ceiling rejects too many unique roots rather than truncating that page.
|
|
277
286
|
#
|
|
278
287
|
# Returns a `ScopedAnalysis`, which destructures:
|
|
279
288
|
#
|
|
@@ -282,7 +291,8 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
282
291
|
# )
|
|
283
292
|
#
|
|
284
293
|
# `unreachable` names roots that changed in the window but have no live row
|
|
285
|
-
# left
|
|
294
|
+
# left, independently of the live page's pagination and safety ceiling.
|
|
295
|
+
# A relation's conditions are evaluated against the live table, so a
|
|
286
296
|
# destroyed root cannot be tested against them at all -- its history is
|
|
287
297
|
# intact and the state it held at destruction may well have matched. Those
|
|
288
298
|
# roots are reported rather than dropped so that a page auditing deletions
|
|
@@ -291,7 +301,7 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
291
301
|
# Note also that a relation selects on current state, not on state during
|
|
292
302
|
# the window: `where(status: 'published')` means published *now*, which is a
|
|
293
303
|
# different set from what was published while the window was open.
|
|
294
|
-
#: (untyped, limit: Integer?, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool, ?version_scope: untyped, ?close_on: Symbol?) -> ScopedAnalysis
|
|
304
|
+
#: (untyped, limit: Integer?, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool, ?version_scope: untyped, ?close_on: Symbol?, ?snapshots: bool, ?group: Symbol?, ?historical_filter: untyped, ?max_filter_versions: Integer, ?include_deleted: bool, ?allow_expensive: bool) -> ScopedAnalysis
|
|
295
305
|
def analyze_scope( # rubocop:disable Metrics/ParameterLists
|
|
296
306
|
scope,
|
|
297
307
|
limit:,
|
|
@@ -300,11 +310,39 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
300
310
|
ignore: DEFAULT_IGNORED_ATTRIBUTES,
|
|
301
311
|
activity: false,
|
|
302
312
|
version_scope: nil,
|
|
303
|
-
close_on: nil
|
|
313
|
+
close_on: nil,
|
|
314
|
+
snapshots: false,
|
|
315
|
+
group: nil,
|
|
316
|
+
historical_filter: nil,
|
|
317
|
+
max_filter_versions: HistoricalFilter::DEFAULT_VERSION_LIMIT,
|
|
318
|
+
include_deleted: false,
|
|
319
|
+
allow_expensive: false
|
|
304
320
|
)
|
|
305
|
-
PaperTrailAdapter.new(associations: associations, ignore: ignore
|
|
321
|
+
adapter = PaperTrailAdapter.new(associations: associations, ignore: ignore,
|
|
322
|
+
allow_expensive: allow_expensive)
|
|
323
|
+
adapter.analyze_scope(
|
|
306
324
|
scope, limit: limit, within: within, activity: activity,
|
|
307
|
-
version_scope: version_scope, close_on: close_on
|
|
325
|
+
version_scope: version_scope, close_on: close_on, snapshots: snapshots, group: group,
|
|
326
|
+
historical_filter: historical_filter, max_filter_versions: max_filter_versions,
|
|
327
|
+
include_deleted: include_deleted
|
|
328
|
+
)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Recent root and selected-child activity through the current saved state.
|
|
332
|
+
# Historical windows remain explicit on analyze_scope; this entry point is
|
|
333
|
+
# deliberately named for a report through now rather than an as-of query.
|
|
334
|
+
#: (untyped, since: untyped, limit: Integer, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?snapshots: bool, ?group: Symbol?, ?include_deleted: bool, ?historical_filter: untyped, ?max_filter_versions: Integer, ?allow_expensive: bool) -> ScopedAnalysis
|
|
335
|
+
def report( # rubocop:disable Metrics/ParameterLists
|
|
336
|
+
scope, since:, limit:, associations: [], ignore: DEFAULT_IGNORED_ATTRIBUTES,
|
|
337
|
+
snapshots: false, group: nil, include_deleted: false, historical_filter: nil,
|
|
338
|
+
max_filter_versions: HistoricalFilter::DEFAULT_VERSION_LIMIT, allow_expensive: false
|
|
339
|
+
)
|
|
340
|
+
analyze_scope(
|
|
341
|
+
scope,
|
|
342
|
+
within: since..Time.now.utc, limit: limit, associations: associations,
|
|
343
|
+
ignore: ignore, activity: true, close_on: :current, snapshots: snapshots, group: group,
|
|
344
|
+
include_deleted: include_deleted, historical_filter: historical_filter,
|
|
345
|
+
max_filter_versions: max_filter_versions, allow_expensive: allow_expensive
|
|
308
346
|
)
|
|
309
347
|
end
|
|
310
348
|
|
|
@@ -344,7 +382,7 @@ module PaperTrailDiff # rubocop:disable Metrics/ModuleLength
|
|
|
344
382
|
# list that merely shifted would otherwise look changed throughout. A key
|
|
345
383
|
# that was absent reads as `NestedComparator::ABSENT` rather than nil, which
|
|
346
384
|
# JSON uses for a present null.
|
|
347
|
-
#: (untyped, ?untyped) ->
|
|
385
|
+
#: (untyped, ?untyped) -> nested_changes
|
|
348
386
|
def nested_changes(change, to_value = nil)
|
|
349
387
|
# Tested by type rather than by responding to `from`: ActiveSupport gives
|
|
350
388
|
# String#from, so duck-typing here quietly reads a plain string as a pair.
|
|
@@ -29,9 +29,6 @@ module PaperTrailDiff
|
|
|
29
29
|
# : (Array[RecordSnapshot], untyped, RecordSnapshot?) -> [Array[RecordSnapshot], bool]
|
|
30
30
|
def replace_existing_target: (Array[RecordSnapshot], untyped, RecordSnapshot?) -> [ Array[RecordSnapshot], bool ]
|
|
31
31
|
|
|
32
|
-
# : (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
|
|
33
|
-
def replace_association: (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
|
|
34
|
-
|
|
35
32
|
# : (untyped, RecordSnapshot?) -> String
|
|
36
33
|
def replacement_type: (untyped, RecordSnapshot?) -> String
|
|
37
34
|
|
|
@@ -54,8 +54,8 @@ module PaperTrailDiff
|
|
|
54
54
|
# : () -> bool
|
|
55
55
|
def destroyed?: () -> bool
|
|
56
56
|
|
|
57
|
-
# : () -> Hash[Symbol, untyped]
|
|
58
|
-
def to_h: () -> Hash[Symbol, untyped]
|
|
57
|
+
# : (?metadata: bool) -> Hash[Symbol, untyped]
|
|
58
|
+
def to_h: (?metadata: bool) -> Hash[Symbol, untyped]
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
# One adjacent transition in a descendant-aware activity timeline.
|
|
@@ -87,7 +87,12 @@ module PaperTrailDiff
|
|
|
87
87
|
# : () -> bool
|
|
88
88
|
def empty?: () -> bool
|
|
89
89
|
|
|
90
|
-
#
|
|
91
|
-
|
|
90
|
+
# The event whose change this step reports. For a transaction group, this
|
|
91
|
+
# is the first event in the group, not necessarily its only actor or record.
|
|
92
|
+
# : () -> ActivityBoundary
|
|
93
|
+
def source_boundary: () -> ActivityBoundary
|
|
94
|
+
|
|
95
|
+
# : (?metadata: bool, ?snapshots: bool) -> Hash[Symbol, untyped]
|
|
96
|
+
def to_h: (?metadata: bool, ?snapshots: bool) -> Hash[Symbol, untyped]
|
|
92
97
|
end
|
|
93
98
|
end
|
|
@@ -9,6 +9,14 @@ module PaperTrailDiff
|
|
|
9
9
|
# : () -> Array[untyped]
|
|
10
10
|
def call: () -> Array[untyped]
|
|
11
11
|
|
|
12
|
+
# One shared query retains the owner and timestamp needed to partition a
|
|
13
|
+
# batch's candidates back into each root's exact activity range.
|
|
14
|
+
# : () -> Array[Array[untyped]]
|
|
15
|
+
def historical_rows: () -> Array[Array[untyped]]
|
|
16
|
+
|
|
17
|
+
# : () -> Array[Array[untyped]]
|
|
18
|
+
def current_pairs: () -> Array[Array[untyped]]
|
|
19
|
+
|
|
12
20
|
private
|
|
13
21
|
|
|
14
22
|
@parent_class: untyped
|
|
@@ -19,6 +27,9 @@ module PaperTrailDiff
|
|
|
19
27
|
|
|
20
28
|
@reflection: untyped
|
|
21
29
|
|
|
30
|
+
# : (Array[Array[untyped]]) -> Array[Array[untyped]]
|
|
31
|
+
def typed_rows: (Array[Array[untyped]]) -> Array[Array[untyped]]
|
|
32
|
+
|
|
22
33
|
# : () -> Array[untyped]
|
|
23
34
|
def historical_ids: () -> Array[untyped]
|
|
24
35
|
|
|
@@ -22,8 +22,8 @@ module PaperTrailDiff
|
|
|
22
22
|
|
|
23
23
|
@route_updater: ActivityCollectionRouteUpdater
|
|
24
24
|
|
|
25
|
-
# : (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped]) -> RecordSnapshot
|
|
26
|
-
def apply_route: (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped]) -> RecordSnapshot
|
|
25
|
+
# : (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped], ?direct: bool) -> RecordSnapshot
|
|
26
|
+
def apply_route: (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped], ?direct: bool) -> RecordSnapshot
|
|
27
27
|
|
|
28
28
|
# : (Array[Array[untyped]], untyped) -> bool
|
|
29
29
|
def unsafe_through_membership_event?: (Array[Array[untyped]], untyped) -> bool
|
|
@@ -31,8 +31,8 @@ module PaperTrailDiff
|
|
|
31
31
|
# : (Array[Array[untyped]], ActivitySnapshotDelta?) -> bool
|
|
32
32
|
def unsafe_nested_membership_delta?: (Array[Array[untyped]], ActivitySnapshotDelta?) -> bool
|
|
33
33
|
|
|
34
|
-
# : (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped]) -> [untyped, RecordSnapshot?]
|
|
35
|
-
def route_event_state: (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped]) -> [ untyped, RecordSnapshot? ]
|
|
34
|
+
# : (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped], ?direct: bool) -> [untyped, RecordSnapshot?]
|
|
35
|
+
def route_event_state: (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, Array[untyped], ?direct: bool) -> [ untyped, RecordSnapshot? ]
|
|
36
36
|
|
|
37
37
|
# : (untyped, Array[untyped], SnapshotNormalizer, Array[untyped]) -> RecordSnapshot?
|
|
38
38
|
def normalized_event_record: (untyped, Array[untyped], SnapshotNormalizer, Array[untyped]) -> RecordSnapshot?
|
|
@@ -37,8 +37,5 @@ module PaperTrailDiff
|
|
|
37
37
|
|
|
38
38
|
# : (AssociationSnapshot, untyped, ActivityCollectionRouteChange) -> Integer?
|
|
39
39
|
def nested_owner_position: (AssociationSnapshot, untyped, ActivityCollectionRouteChange) -> Integer?
|
|
40
|
-
|
|
41
|
-
# : (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
|
|
42
|
-
def replace_association: (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
|
|
43
40
|
end
|
|
44
41
|
end
|
|
@@ -5,11 +5,17 @@ module PaperTrailDiff
|
|
|
5
5
|
class ActivityEventRecordResolver
|
|
6
6
|
RECORD_AFTER_HANDLERS: untyped
|
|
7
7
|
|
|
8
|
-
# : (?record_transition: untyped) -> void
|
|
9
|
-
def initialize: (?record_transition: untyped) -> void
|
|
8
|
+
# : (?record_transition: untyped, ?prepared_record_after: untyped) -> void
|
|
9
|
+
def initialize: (?record_transition: untyped, ?prepared_record_after: untyped) -> void
|
|
10
|
+
|
|
11
|
+
# : (untyped, ?direct: bool) -> untyped
|
|
12
|
+
def record_after: (untyped, ?direct: bool) -> untyped
|
|
13
|
+
|
|
14
|
+
# : (untyped) -> [bool, untyped]
|
|
15
|
+
def direct_after: (untyped) -> [ bool, untyped ]
|
|
10
16
|
|
|
11
17
|
# : (untyped) -> untyped
|
|
12
|
-
def
|
|
18
|
+
def fallback_record_after: (untyped) -> untyped
|
|
13
19
|
|
|
14
20
|
# : (untyped) -> ActivitySnapshotDelta?
|
|
15
21
|
def snapshot_delta: (untyped) -> ActivitySnapshotDelta?
|
|
@@ -30,8 +36,18 @@ module PaperTrailDiff
|
|
|
30
36
|
|
|
31
37
|
private
|
|
32
38
|
|
|
39
|
+
@direct_loader: DirectRecordStateLoader
|
|
40
|
+
|
|
41
|
+
@prepared_record_after: untyped
|
|
42
|
+
|
|
33
43
|
@record_transition: untyped
|
|
34
44
|
|
|
45
|
+
# : (untyped) -> PreparedRecordState?
|
|
46
|
+
def direct_record_after: (untyped) -> PreparedRecordState?
|
|
47
|
+
|
|
48
|
+
# : (untyped) -> untyped
|
|
49
|
+
def prepared_changeset: (untyped) -> untyped
|
|
50
|
+
|
|
35
51
|
# : (untyped, untyped) -> Hash[untyped, untyped]
|
|
36
52
|
def after_attributes: (untyped, untyped) -> Hash[untyped, untyped]
|
|
37
53
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module PaperTrailDiff
|
|
4
4
|
# Dispatches safe descendant events to focused immutable snapshot appliers.
|
|
5
5
|
class ActivityEventSnapshotRefresher
|
|
6
|
-
# : (traversal: AssociationTraversal, pool: SnapshotPool, components: untyped, ?association_reader: untyped, ?record_transition: untyped) -> void
|
|
7
|
-
def initialize: (traversal: AssociationTraversal, pool: SnapshotPool, components: untyped, ?association_reader: untyped, ?record_transition: untyped) -> void
|
|
6
|
+
# : (traversal: AssociationTraversal, pool: SnapshotPool, components: untyped, ?association_reader: untyped, ?record_transition: untyped, ?prepared_record_after: untyped) -> void
|
|
7
|
+
def initialize: (traversal: AssociationTraversal, pool: SnapshotPool, components: untyped, ?association_reader: untyped, ?record_transition: untyped, ?prepared_record_after: untyped) -> void
|
|
8
8
|
|
|
9
9
|
# : (SnapshotPool, untyped) -> void
|
|
10
10
|
def configure_appliers: (SnapshotPool, untyped) -> void
|
|
@@ -6,6 +6,9 @@ module PaperTrailDiff
|
|
|
6
6
|
# window -- but a transaction has to collapse the same way in both, or the
|
|
7
7
|
# same history would read differently depending on how it was asked for.
|
|
8
8
|
module ActivityGrouping
|
|
9
|
+
# : (Symbol?, ?activity: bool, ?snapshots: bool) -> void
|
|
10
|
+
def self.validate!: (Symbol?, ?activity: bool, ?snapshots: bool) -> void
|
|
11
|
+
|
|
9
12
|
private
|
|
10
13
|
|
|
11
14
|
# : () -> bool
|
|
@@ -11,8 +11,12 @@ module PaperTrailDiff
|
|
|
11
11
|
|
|
12
12
|
attr_reader last_snapshot: RecordSnapshot?
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
attr_reader last_boundary: ActivityBoundary?
|
|
15
|
+
|
|
16
|
+
attr_reader last_event_snapshot: RecordSnapshot?
|
|
17
|
+
|
|
18
|
+
# : (steps: Array[ActivityStep], root_snapshots: Hash[Array[untyped], RecordSnapshot?], first_snapshot: RecordSnapshot?, last_snapshot: RecordSnapshot?, ?last_boundary: ActivityBoundary?, ?last_event_snapshot: RecordSnapshot?) -> void
|
|
19
|
+
def initialize: (steps: Array[ActivityStep], root_snapshots: Hash[Array[untyped], RecordSnapshot?], first_snapshot: RecordSnapshot?, last_snapshot: RecordSnapshot?, ?last_boundary: ActivityBoundary?, ?last_event_snapshot: RecordSnapshot?) -> void
|
|
16
20
|
|
|
17
21
|
# : () -> ActivityHistory
|
|
18
22
|
def self.empty: () -> ActivityHistory
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module PaperTrailDiff
|
|
4
4
|
# Optional full/partial snapshot operations consumed by the activity sequence.
|
|
5
5
|
class ActivitySnapshotProvider
|
|
6
|
-
# : (snapshotter: untyped, refresher: untyped, preparer: untyped) -> void
|
|
7
|
-
def initialize: (snapshotter: untyped, refresher: untyped, preparer: untyped) -> void
|
|
6
|
+
# : (snapshotter: untyped, refresher: untyped, preparer: untyped, ?activity_index: untyped) -> void
|
|
7
|
+
def initialize: (snapshotter: untyped, refresher: untyped, preparer: untyped, ?activity_index: untyped) -> void
|
|
8
8
|
|
|
9
9
|
# : (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
10
10
|
def prepare: (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
@@ -18,6 +18,11 @@ module PaperTrailDiff
|
|
|
18
18
|
# : (untyped, untyped, RecordSnapshot?, event: ActivityEvent) -> RecordSnapshot?
|
|
19
19
|
def advance_root: (untyped, untyped, RecordSnapshot?, event: ActivityEvent) -> RecordSnapshot?
|
|
20
20
|
|
|
21
|
+
# : () -> PreparedActivityIndex?
|
|
22
|
+
def activity_index: () -> PreparedActivityIndex?
|
|
23
|
+
|
|
24
|
+
@activity_index: untyped
|
|
25
|
+
|
|
21
26
|
@preparer: untyped
|
|
22
27
|
|
|
23
28
|
@refresher: untyped
|
|
@@ -44,6 +44,14 @@ module PaperTrailDiff
|
|
|
44
44
|
# : () -> Array[ActivityStep]
|
|
45
45
|
def build_to_current: () -> Array[ActivityStep]
|
|
46
46
|
|
|
47
|
+
# : () -> Analysis
|
|
48
|
+
def analyze_current: () -> Analysis
|
|
49
|
+
|
|
50
|
+
# The explicit live endpoint and a batch's live closing endpoint use the
|
|
51
|
+
# same selected plan. A version filter can close earlier, on its successor.
|
|
52
|
+
# : () -> [RootVersionPlan, Array[ActivityEvent], ActivityHistory, RecordSnapshot?, ActivityBoundary?]
|
|
53
|
+
def current_history: () -> [ RootVersionPlan, Array[ActivityEvent], ActivityHistory, RecordSnapshot?, ActivityBoundary? ]
|
|
54
|
+
|
|
47
55
|
# : () -> [RecordSnapshot?, untyped]
|
|
48
56
|
def capture_current: () -> [ RecordSnapshot?, untyped ]
|
|
49
57
|
|
|
@@ -56,9 +64,6 @@ module PaperTrailDiff
|
|
|
56
64
|
# : (Array[untyped], ?end_at: untyped) -> void
|
|
57
65
|
def prepare_history: (Array[untyped], ?end_at: untyped) -> void
|
|
58
66
|
|
|
59
|
-
# : (Array[untyped], Array[ActivityEvent], ?current: untyped, ?final_boundary: ActivityBoundary?, ?final_snapshot: RecordSnapshot?) -> Array[ActivityStep]
|
|
60
|
-
def build_event_steps: (Array[untyped], Array[ActivityEvent], ?current: untyped, ?final_boundary: ActivityBoundary?, ?final_snapshot: RecordSnapshot?) -> Array[ActivityStep]
|
|
61
|
-
|
|
62
67
|
# Appends the transition into an explicit closing boundary, which is either
|
|
63
68
|
# a requested current record or the absence a final root destroy leaves.
|
|
64
69
|
# : (ActivityHistory, Array[ActivityEvent], ActivityBoundary?, RecordSnapshot?) -> Array[ActivityStep]
|
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
module PaperTrailDiff
|
|
4
4
|
# Collects root and selected-descendant versions relevant to one root history range.
|
|
5
5
|
class ActivityVersionCollector
|
|
6
|
-
# : (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped) -> void
|
|
7
|
-
def initialize: (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped) -> void
|
|
6
|
+
# : (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped, ?prepared: PreparedActivityIndex?) -> void
|
|
7
|
+
def initialize: (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped, ?prepared: PreparedActivityIndex?) -> void
|
|
8
8
|
|
|
9
9
|
# : () -> Array[ActivityEvent]
|
|
10
10
|
def call: () -> Array[ActivityEvent]
|
|
11
11
|
|
|
12
12
|
private
|
|
13
13
|
|
|
14
|
+
@prepared: PreparedActivityIndex?
|
|
15
|
+
|
|
14
16
|
@range: ActivityRange
|
|
15
17
|
|
|
16
18
|
@record: untyped
|
|
@@ -58,11 +60,5 @@ module PaperTrailDiff
|
|
|
58
60
|
|
|
59
61
|
# : (untyped, untyped) -> untyped
|
|
60
62
|
def target_class: (untyped, untyped) -> untyped
|
|
61
|
-
|
|
62
|
-
# : (untyped) -> bool
|
|
63
|
-
def in_range?: (untyped) -> bool
|
|
64
|
-
|
|
65
|
-
# : (String, String) -> String
|
|
66
|
-
def join_path: (String, String) -> String
|
|
67
63
|
end
|
|
68
64
|
end
|
|
@@ -26,7 +26,7 @@ module PaperTrailDiff
|
|
|
26
26
|
# Reconstructed endpoint states are opt-in, because they carry the whole
|
|
27
27
|
# selected graph whether or not anything changed, which dwarfs the rest of
|
|
28
28
|
# the payload for a wide graph.
|
|
29
|
-
# : (?snapshots: bool) -> Hash[Symbol, untyped]
|
|
30
|
-
def to_h: (?snapshots: bool) -> Hash[Symbol, untyped]
|
|
29
|
+
# : (?snapshots: bool, ?metadata: bool) -> Hash[Symbol, untyped]
|
|
30
|
+
def to_h: (?snapshots: bool, ?metadata: bool) -> Hash[Symbol, untyped]
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -5,8 +5,8 @@ module PaperTrailDiff
|
|
|
5
5
|
# versions and preparing their association history once for the whole batch
|
|
6
6
|
# rather than once per root.
|
|
7
7
|
class AnalysisBatch
|
|
8
|
-
# : (Array[untyped], time_range: TimeRange?, live_loader: untyped, history_preparer: untyped, analyzer: untyped, ?version_scope: untyped, ?close_on_current: bool) -> void
|
|
9
|
-
def initialize: (Array[untyped], time_range: TimeRange?, live_loader: untyped, history_preparer: untyped, analyzer: untyped, ?version_scope: untyped, ?close_on_current: bool) -> void
|
|
8
|
+
# : (Array[untyped], time_range: TimeRange?, live_loader: untyped, history_preparer: untyped, analyzer: untyped, ?version_scope: untyped, ?close_on_current: bool, ?context_required: bool) -> void
|
|
9
|
+
def initialize: (Array[untyped], time_range: TimeRange?, live_loader: untyped, history_preparer: untyped, analyzer: untyped, ?version_scope: untyped, ?close_on_current: bool, ?context_required: bool) -> void
|
|
10
10
|
|
|
11
11
|
# : () -> Hash[identity, Analysis]
|
|
12
12
|
def call: () -> Hash[identity, Analysis]
|
|
@@ -17,6 +17,8 @@ module PaperTrailDiff
|
|
|
17
17
|
|
|
18
18
|
@close_on_current: bool
|
|
19
19
|
|
|
20
|
+
@context_required: bool
|
|
21
|
+
|
|
20
22
|
@history_preparer: untyped
|
|
21
23
|
|
|
22
24
|
@live_loader: untyped
|
|
@@ -43,8 +45,17 @@ module PaperTrailDiff
|
|
|
43
45
|
# : (Array[untyped], Hash[Array[String], RootVersionPlan], Hash[Array[String], untyped]) -> void
|
|
44
46
|
def prepare: (Array[untyped], Hash[Array[String], RootVersionPlan], Hash[Array[String], untyped]) -> void
|
|
45
47
|
|
|
48
|
+
# : (Array[untyped], Hash[Array[String], RootVersionPlan]) -> bool
|
|
49
|
+
def closes_live?: (Array[untyped], Hash[Array[String], RootVersionPlan]) -> bool
|
|
50
|
+
|
|
51
|
+
# A plan closing on the live record reads history up to now; the others
|
|
52
|
+
# stop at the window, so a past window does not load everything since.
|
|
53
|
+
# : (Array[untyped], ?live: bool) -> Hash[Symbol, untyped]
|
|
54
|
+
def preparation_range: (Array[untyped], ?live: bool) -> Hash[Symbol, untyped]
|
|
55
|
+
|
|
46
56
|
# A root with no versions in range has nothing to report, which is an empty
|
|
47
|
-
# result rather than a failed request
|
|
57
|
+
# result rather than a failed request -- unless an activity view closes it
|
|
58
|
+
# on current state, where its descendants may still have moved.
|
|
48
59
|
# : (untyped, RootVersionPlan) -> Analysis
|
|
49
60
|
def analysis_for: (untyped, RootVersionPlan) -> Analysis
|
|
50
61
|
end
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
module PaperTrailDiff
|
|
4
4
|
# Resolves and validates ActiveRecord reflections for a bounded association tree.
|
|
5
5
|
class AssociationTraversal
|
|
6
|
+
# The class a `belongs_to` points at for this record, reading a polymorphic
|
|
7
|
+
# type column when there is one. Nil when that type names no class.
|
|
8
|
+
# : (untyped, untyped) -> untyped
|
|
9
|
+
def self.belongs_to_target: (untyped, untyped) -> untyped
|
|
10
|
+
|
|
6
11
|
# : (AssociationTree) -> void
|
|
7
12
|
def initialize: (AssociationTree) -> void
|
|
8
13
|
|
|
@@ -18,6 +23,12 @@ module PaperTrailDiff
|
|
|
18
23
|
# : (untyped) -> Array[String]
|
|
19
24
|
def habtm_paths: (untyped) -> Array[String]
|
|
20
25
|
|
|
26
|
+
# HABTM join rows have no versions of their own, so membership changes
|
|
27
|
+
# cannot be split into events once a range runs past the last root version
|
|
28
|
+
# into live state.
|
|
29
|
+
# : (untyped) -> void
|
|
30
|
+
def reject_live_habtm_activity!: (untyped) -> void
|
|
31
|
+
|
|
21
32
|
# : (untyped, AssociationTree, path: String) -> Array[untyped]
|
|
22
33
|
def reflections_for: (untyped, AssociationTree, path: String) -> Array[untyped]
|
|
23
34
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Generated from lib/paper_trail_diff/batch_boundary_resolver.rb with RBS::Inline
|
|
2
2
|
|
|
3
3
|
module PaperTrailDiff
|
|
4
|
-
# Resolves `:first`
|
|
4
|
+
# Resolves `:first` endpoints for a whole batch in a fixed number of queries per
|
|
5
5
|
# model class. Left to the caller this is a per-root lookup, which reintroduces
|
|
6
6
|
# exactly the queries a batched comparison exists to remove.
|
|
7
7
|
class BatchBoundaryResolver
|
|
@@ -46,15 +46,12 @@ module PaperTrailDiff
|
|
|
46
46
|
# : (Hash[Array[String], Hash[Symbol, untyped]], untyped, Array[untyped]) -> void
|
|
47
47
|
def add_model_boundaries: (Hash[Array[String], Hash[Symbol, untyped]], untyped, Array[untyped]) -> void
|
|
48
48
|
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
# string form rather than assuming integers.
|
|
56
|
-
# : (Hash[untyped, untyped], untyped) -> untyped
|
|
57
|
-
def boundary_key: (Hash[untyped, untyped], untyped) -> untyped
|
|
49
|
+
# Each root's earliest version by time, in one query whatever the size of
|
|
50
|
+
# the batch. The lowest id is not the earliest version when ids are not
|
|
51
|
+
# sequential, as with UUIDs, so time decides and the usual ordering breaks
|
|
52
|
+
# a tie -- refusing one that ids cannot order.
|
|
53
|
+
# : (untyped, Array[untyped]) -> Hash[String, untyped]
|
|
54
|
+
def first_versions: (untyped, Array[untyped]) -> Hash[String, untyped]
|
|
58
55
|
|
|
59
56
|
# : (untyped, untyped) -> Array[String]
|
|
60
57
|
def identity_key: (untyped, untyped) -> Array[String]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Generated from lib/paper_trail_diff/batch_safety.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module PaperTrailDiff
|
|
4
|
+
# Refuses known per-record association loading before a batch reconstructs it.
|
|
5
|
+
class BatchSafety
|
|
6
|
+
# : (AssociationTraversal, allow_expensive: bool) -> void
|
|
7
|
+
def initialize: (AssociationTraversal, allow_expensive: bool) -> void
|
|
8
|
+
|
|
9
|
+
# : (untyped, ?historical: bool) -> void
|
|
10
|
+
def call: (untyped, ?historical: bool) -> void
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
@allow_expensive: bool
|
|
15
|
+
|
|
16
|
+
@traversal: AssociationTraversal
|
|
17
|
+
|
|
18
|
+
# : (untyped, String, bool) -> void
|
|
19
|
+
def check: (untyped, String, bool) -> void
|
|
20
|
+
|
|
21
|
+
# : (untyped, bool) -> String?
|
|
22
|
+
def reason_for: (untyped, bool) -> String?
|
|
23
|
+
end
|
|
24
|
+
end
|