paper_trail_diff 0.14.0 → 0.15.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 +343 -0
- data/QUICKSTART.md +21 -4
- data/README.md +58 -55
- data/docs/architecture.md +32 -11
- data/docs/performance.md +116 -391
- data/docs/reference.md +345 -106
- data/docs/testing.md +63 -7
- data/lib/paper_trail_diff/activity_boundary.rb +83 -26
- data/lib/paper_trail_diff/activity_child_candidate_loader.rb +2 -1
- data/lib/paper_trail_diff/activity_event.rb +41 -10
- data/lib/paper_trail_diff/activity_history.rb +34 -9
- data/lib/paper_trail_diff/activity_range.rb +18 -3
- data/lib/paper_trail_diff/activity_snapshot_sequence.rb +76 -37
- data/lib/paper_trail_diff/activity_target_candidate_loader.rb +5 -5
- data/lib/paper_trail_diff/activity_timeline_builder.rb +266 -111
- data/lib/paper_trail_diff/activity_transaction_grouper.rb +2 -1
- data/lib/paper_trail_diff/activity_tree_filter.rb +114 -0
- data/lib/paper_trail_diff/activity_version_collector.rb +7 -5
- data/lib/paper_trail_diff/activity_view.rb +69 -0
- data/lib/paper_trail_diff/analysis.rb +13 -1
- data/lib/paper_trail_diff/analysis_batch.rb +24 -30
- data/lib/paper_trail_diff/approximate_paths.rb +48 -0
- data/lib/paper_trail_diff/association_activity_edge.rb +6 -6
- data/lib/paper_trail_diff/association_discovery.rb +9 -1
- data/lib/paper_trail_diff/association_key.rb +56 -0
- data/lib/paper_trail_diff/association_traversal.rb +13 -4
- data/lib/paper_trail_diff/batch_boundary_resolver.rb +3 -4
- data/lib/paper_trail_diff/batch_preload.rb +53 -0
- data/lib/paper_trail_diff/batched_root_analyzer.rb +12 -14
- data/lib/paper_trail_diff/batched_root_versions.rb +38 -14
- data/lib/paper_trail_diff/change_row.rb +133 -0
- data/lib/paper_trail_diff/collection_comparator.rb +5 -32
- data/lib/paper_trail_diff/configuration.rb +35 -12
- data/lib/paper_trail_diff/deleted_analysis_batch.rb +18 -18
- data/lib/paper_trail_diff/deleted_root_filter.rb +79 -0
- data/lib/paper_trail_diff/deprecation.rb +61 -0
- data/lib/paper_trail_diff/diagnostics.rb +84 -99
- data/lib/paper_trail_diff/endpoint.rb +26 -3
- data/lib/paper_trail_diff/errors.rb +3 -1
- data/lib/paper_trail_diff/fallback_paths.rb +38 -0
- data/lib/paper_trail_diff/historical_association_reifier.rb +2 -4
- data/lib/paper_trail_diff/historical_filter.rb +19 -10
- data/lib/paper_trail_diff/historical_snapshot_store.rb +57 -67
- data/lib/paper_trail_diff/live_endpoint_batch_loader.rb +1 -35
- data/lib/paper_trail_diff/nested_comparator.rb +19 -18
- data/lib/paper_trail_diff/paper_trail_adapter.rb +122 -127
- data/lib/paper_trail_diff/preloaded_endpoint_batch_loader.rb +13 -1
- data/lib/paper_trail_diff/prepared_activity_index.rb +1 -1
- data/lib/paper_trail_diff/prepared_edge_loader.rb +2 -1
- data/lib/paper_trail_diff/prepared_history.rb +9 -1
- data/lib/paper_trail_diff/prepared_history_loader.rb +1 -0
- data/lib/paper_trail_diff/prepared_record_index.rb +38 -7
- data/lib/paper_trail_diff/root_version_selection.rb +4 -2
- data/lib/paper_trail_diff/scope_condition.rb +76 -21
- data/lib/paper_trail_diff/scope_ranking.rb +12 -2
- data/lib/paper_trail_diff/scoped_analysis.rb +11 -0
- data/lib/paper_trail_diff/scoped_analysis_builder.rb +16 -8
- data/lib/paper_trail_diff/scoped_root_selection.rb +18 -12
- data/lib/paper_trail_diff/snapshot.rb +16 -1
- data/lib/paper_trail_diff/support.rb +29 -2
- data/lib/paper_trail_diff/time_range.rb +32 -10
- data/lib/paper_trail_diff/timeline_builder.rb +7 -7
- data/lib/paper_trail_diff/timeline_range.rb +9 -1
- data/lib/paper_trail_diff/timeline_snapshot_provider.rb +24 -17
- data/lib/paper_trail_diff/transaction_cut.rb +181 -0
- data/lib/paper_trail_diff/traversal_preparer.rb +134 -29
- data/lib/paper_trail_diff/version.rb +1 -1
- data/lib/paper_trail_diff/version_boundary.rb +37 -8
- data/lib/paper_trail_diff/version_query.rb +34 -10
- data/lib/paper_trail_diff/version_scope_filter.rb +9 -10
- data/lib/paper_trail_diff/version_sequence_diagnostics.rb +31 -16
- data/lib/paper_trail_diff/version_table.rb +60 -0
- data/lib/paper_trail_diff.rb +98 -56
- data/sig/generated/paper_trail_diff/activity_boundary.rbs +54 -19
- data/sig/generated/paper_trail_diff/activity_event.rbs +25 -4
- data/sig/generated/paper_trail_diff/activity_history.rbs +21 -6
- data/sig/generated/paper_trail_diff/activity_range.rbs +9 -2
- data/sig/generated/paper_trail_diff/activity_snapshot_sequence.rbs +48 -9
- data/sig/generated/paper_trail_diff/activity_timeline_builder.rbs +134 -30
- data/sig/generated/paper_trail_diff/activity_tree_filter.rbs +73 -0
- data/sig/generated/paper_trail_diff/activity_version_collector.rbs +2 -0
- data/sig/generated/paper_trail_diff/activity_view.rbs +42 -0
- data/sig/generated/paper_trail_diff/analysis.rbs +8 -1
- data/sig/generated/paper_trail_diff/analysis_batch.rbs +8 -15
- data/sig/generated/paper_trail_diff/approximate_paths.rbs +23 -0
- data/sig/generated/paper_trail_diff/association_discovery.rbs +5 -0
- data/sig/generated/paper_trail_diff/association_key.rbs +29 -0
- data/sig/generated/paper_trail_diff/association_traversal.rbs +4 -0
- data/sig/generated/paper_trail_diff/batch_preload.rbs +29 -0
- data/sig/generated/paper_trail_diff/batched_root_analyzer.rbs +9 -10
- data/sig/generated/paper_trail_diff/batched_root_versions.rbs +14 -4
- data/sig/generated/paper_trail_diff/change_row.rbs +86 -0
- data/sig/generated/paper_trail_diff/collection_comparator.rbs +2 -16
- data/sig/generated/paper_trail_diff/configuration.rbs +19 -3
- data/sig/generated/paper_trail_diff/deleted_analysis_batch.rbs +8 -8
- data/sig/generated/paper_trail_diff/deleted_root_filter.rbs +48 -0
- data/sig/generated/paper_trail_diff/deprecation.rbs +35 -0
- data/sig/generated/paper_trail_diff/diagnostics.rbs +37 -30
- data/sig/generated/paper_trail_diff/endpoint.rbs +11 -2
- data/sig/generated/paper_trail_diff/errors.rbs +3 -1
- data/sig/generated/paper_trail_diff/fallback_paths.rbs +22 -0
- data/sig/generated/paper_trail_diff/historical_filter.rbs +12 -2
- data/sig/generated/paper_trail_diff/historical_snapshot_store.rbs +33 -28
- data/sig/generated/paper_trail_diff/live_endpoint_batch_loader.rbs +0 -15
- data/sig/generated/paper_trail_diff/nested_comparator.rbs +10 -7
- data/sig/generated/paper_trail_diff/paper_trail_adapter.rbs +54 -52
- data/sig/generated/paper_trail_diff/preloaded_endpoint_batch_loader.rbs +9 -1
- data/sig/generated/paper_trail_diff/prepared_history.rbs +5 -0
- data/sig/generated/paper_trail_diff/prepared_record_index.rbs +19 -2
- data/sig/generated/paper_trail_diff/root_version_selection.rbs +2 -0
- data/sig/generated/paper_trail_diff/scope_condition.rbs +43 -9
- data/sig/generated/paper_trail_diff/scope_ranking.rbs +8 -0
- data/sig/generated/paper_trail_diff/scoped_analysis.rbs +6 -0
- data/sig/generated/paper_trail_diff/scoped_analysis_builder.rbs +6 -1
- data/sig/generated/paper_trail_diff/scoped_root_selection.rbs +8 -4
- data/sig/generated/paper_trail_diff/snapshot.rbs +8 -0
- data/sig/generated/paper_trail_diff/support.rbs +15 -0
- data/sig/generated/paper_trail_diff/time_range.rbs +20 -6
- data/sig/generated/paper_trail_diff/timeline_builder.rbs +2 -2
- data/sig/generated/paper_trail_diff/timeline_range.rbs +2 -0
- data/sig/generated/paper_trail_diff/timeline_snapshot_provider.rbs +17 -7
- data/sig/generated/paper_trail_diff/transaction_cut.rbs +94 -0
- data/sig/generated/paper_trail_diff/traversal_preparer.rbs +66 -8
- data/sig/generated/paper_trail_diff/version_boundary.rbs +20 -3
- data/sig/generated/paper_trail_diff/version_query.rbs +18 -2
- data/sig/generated/paper_trail_diff/version_scope_filter.rbs +4 -5
- data/sig/generated/paper_trail_diff/version_sequence_diagnostics.rbs +16 -9
- data/sig/generated/paper_trail_diff/version_table.rbs +30 -0
- data/sig/generated/paper_trail_diff.rbs +29 -26
- metadata +46 -10
- data/lib/paper_trail_diff/activity_grouping.rb +0 -38
- data/lib/paper_trail_diff/batch_safety.rb +0 -63
- data/lib/paper_trail_diff/time_activity_timeline_builder.rb +0 -223
- data/sig/generated/paper_trail_diff/activity_grouping.rbs +0 -22
- data/sig/generated/paper_trail_diff/batch_safety.rbs +0 -30
- data/sig/generated/paper_trail_diff/time_activity_timeline_builder.rbs +0 -92
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# Generated from lib/paper_trail_diff/historical_snapshot_store.rb with RBS::Inline
|
|
2
2
|
|
|
3
3
|
module PaperTrailDiff
|
|
4
|
-
# Reconstructs and caches immutable historical snapshots for one adapter
|
|
4
|
+
# Reconstructs and caches immutable historical snapshots for one adapter
|
|
5
|
+
# configuration. It keeps the histories batches prepare, by root version;
|
|
6
|
+
# one prepared for a single root goes back to the caller, who passes it to
|
|
7
|
+
# every read for that root.
|
|
5
8
|
class HistoricalSnapshotStore
|
|
6
9
|
# : (tree: AssociationTree, traversal: AssociationTraversal, normalizer: SnapshotNormalizer, preparer: untyped) -> void
|
|
7
10
|
def initialize: (tree: AssociationTree, traversal: AssociationTraversal, normalizer: SnapshotNormalizer, preparer: untyped) -> void
|
|
8
11
|
|
|
9
|
-
# : (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) ->
|
|
10
|
-
def prepare: (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) ->
|
|
12
|
+
# : (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) -> PreparedHistory?
|
|
13
|
+
def prepare: (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) -> PreparedHistory?
|
|
11
14
|
|
|
12
15
|
# : (Array[untyped], Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
13
16
|
def prepare_batch: (Array[untyped], Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
@@ -18,37 +21,29 @@ module PaperTrailDiff
|
|
|
18
21
|
# : (Array[untyped], Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
19
22
|
def prepare_deleted_batch: (Array[untyped], Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
20
23
|
|
|
21
|
-
#
|
|
22
|
-
|
|
24
|
+
# `history` is the one `prepare` returned for this root, if any.
|
|
25
|
+
# : (untyped, untyped, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
26
|
+
def call: (untyped, untyped, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
23
27
|
|
|
24
|
-
# : (untyped, untyped) -> RecordSnapshot?
|
|
25
|
-
def uncached: (untyped, untyped) -> RecordSnapshot?
|
|
28
|
+
# : (untyped, untyped, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
29
|
+
def uncached: (untyped, untyped, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
26
30
|
|
|
27
|
-
# : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?
|
|
28
|
-
def custom: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?
|
|
31
|
+
# : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
32
|
+
def custom: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
29
33
|
|
|
30
|
-
# : (untyped, habtm_version: untyped) -> untyped
|
|
31
|
-
def association_reader: (untyped, habtm_version: untyped) -> untyped
|
|
32
|
-
|
|
33
|
-
# : () -> PreparedActivityIndex?
|
|
34
|
-
def activity_index: () -> PreparedActivityIndex?
|
|
35
|
-
|
|
36
|
-
# : (untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?
|
|
37
|
-
def record_transition: (untyped) -> [ Hash[untyped, untyped], Hash[untyped, untyped] ]?
|
|
38
|
-
|
|
39
|
-
# : (untyped, ?direct: bool) -> [bool, untyped]
|
|
40
|
-
def record_after: (untyped, ?direct: bool) -> [ bool, untyped ]
|
|
34
|
+
# : (untyped, habtm_version: untyped, ?history: PreparedHistory?) -> untyped
|
|
35
|
+
def association_reader: (untyped, habtm_version: untyped, ?history: PreparedHistory?) -> untyped
|
|
41
36
|
|
|
42
37
|
private
|
|
43
38
|
|
|
44
39
|
@live_graph_collector: LiveGraphCollector
|
|
45
40
|
|
|
41
|
+
@live_roots: Hash[identity, untyped]
|
|
42
|
+
|
|
46
43
|
@normalizer: SnapshotNormalizer
|
|
47
44
|
|
|
48
45
|
@prepared_histories: Hash[Array[untyped], PreparedHistory]
|
|
49
46
|
|
|
50
|
-
@prepared_history: PreparedHistory?
|
|
51
|
-
|
|
52
47
|
@prepared_snapshotter: PreparedSnapshotBuilder
|
|
53
48
|
|
|
54
49
|
@preparer: untyped
|
|
@@ -59,6 +54,10 @@ module PaperTrailDiff
|
|
|
59
54
|
|
|
60
55
|
@tree: AssociationTree
|
|
61
56
|
|
|
57
|
+
# A batch's history for the version wins over the one a caller passes.
|
|
58
|
+
# : (untyped, PreparedHistory?) -> PreparedHistory?
|
|
59
|
+
def history_for: (untyped, PreparedHistory?) -> PreparedHistory?
|
|
60
|
+
|
|
62
61
|
# : (untyped) -> Array[untyped]
|
|
63
62
|
def context_key: (untyped) -> Array[untyped]
|
|
64
63
|
|
|
@@ -68,14 +67,20 @@ module PaperTrailDiff
|
|
|
68
67
|
# : (Array[untyped], Array[untyped], ?live_records: Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
69
68
|
def register_batch: (Array[untyped], Array[untyped], ?live_records: Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
|
|
70
69
|
|
|
71
|
-
# : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?
|
|
72
|
-
def snapshot_from_version: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?
|
|
70
|
+
# : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, history: PreparedHistory?) -> RecordSnapshot?
|
|
71
|
+
def snapshot_from_version: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, history: PreparedHistory?) -> RecordSnapshot?
|
|
72
|
+
|
|
73
|
+
# : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, history: PreparedHistory?) -> RecordSnapshot?
|
|
74
|
+
def snapshot_from_live_root: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, history: PreparedHistory?) -> RecordSnapshot?
|
|
73
75
|
|
|
74
|
-
#
|
|
75
|
-
|
|
76
|
+
# Rebuilding a version's associations writes them onto the record, so each
|
|
77
|
+
# snapshot gets its own copy of a batch's loaded row, built from the row's
|
|
78
|
+
# stored values without a query.
|
|
79
|
+
# : (untyped) -> untyped
|
|
80
|
+
def live_root: (untyped) -> untyped
|
|
76
81
|
|
|
77
|
-
# : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, habtm_version: untyped) -> RecordSnapshot?
|
|
78
|
-
def normalize: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, habtm_version: untyped) -> RecordSnapshot?
|
|
82
|
+
# : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, habtm_version: untyped, history: PreparedHistory?) -> RecordSnapshot?
|
|
83
|
+
def normalize: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer, habtm_version: untyped, history: PreparedHistory?) -> RecordSnapshot?
|
|
79
84
|
|
|
80
85
|
# : (untyped, untyped) -> Array[untyped]
|
|
81
86
|
def snapshot_key: (untyped, untyped) -> Array[untyped]
|
|
@@ -39,21 +39,6 @@ module PaperTrailDiff
|
|
|
39
39
|
# : () -> untyped
|
|
40
40
|
def active_record_preloader: () -> untyped
|
|
41
41
|
|
|
42
|
-
# The preloader applies a limit or offset to all owners' records at once,
|
|
43
|
-
# not to each owner's, so such an association is loaded per record. A
|
|
44
|
-
# has_one is no exception. Through a part with a limit, an offset or a
|
|
45
|
-
# has_one cut, the preloader keeps what the part alone would load, while
|
|
46
|
-
# the through's own query keeps the part's conditions only.
|
|
47
|
-
# : (untyped, untyped) -> bool
|
|
48
|
-
def batch_safe?: (untyped, untyped) -> bool
|
|
49
|
-
|
|
50
|
-
# : (untyped) -> bool
|
|
51
|
-
def cut_part?: (untyped) -> bool
|
|
52
|
-
|
|
53
|
-
# Every part a through passes, at any depth.
|
|
54
|
-
# : (untyped) -> Array[untyped]
|
|
55
|
-
def through_parts: (untyped) -> Array[untyped]
|
|
56
|
-
|
|
57
42
|
# : (Array[untyped], untyped) -> Array[untyped]
|
|
58
43
|
def load_individually: (Array[untyped], untyped) -> Array[untyped]
|
|
59
44
|
|
|
@@ -43,6 +43,7 @@ module PaperTrailDiff
|
|
|
43
43
|
# Returns the changed paths, or an empty hash when the pair is not two
|
|
44
44
|
# structures this can look inside. An empty result therefore means "nothing
|
|
45
45
|
# to report at this depth", and the caller still has the whole-value change.
|
|
46
|
+
# Two arrays at the top are one membership change, at the empty path.
|
|
46
47
|
# : () -> nested_changes
|
|
47
48
|
def call: () -> nested_changes
|
|
48
49
|
|
|
@@ -52,14 +53,16 @@ module PaperTrailDiff
|
|
|
52
53
|
|
|
53
54
|
@to_value: untyped
|
|
54
55
|
|
|
55
|
-
# Both sides have to be readable as
|
|
56
|
-
# anything. A column that held text on one side and
|
|
57
|
-
# changed wholesale, and saying so is the accurate report.
|
|
58
|
-
# : () -> [
|
|
59
|
-
def structures: () -> [
|
|
56
|
+
# Both sides have to be readable as the same kind of structure for a
|
|
57
|
+
# nested answer to mean anything. A column that held text on one side and
|
|
58
|
+
# JSON on the other changed wholesale, and saying so is the accurate report.
|
|
59
|
+
# : () -> [untyped, untyped]
|
|
60
|
+
def structures: () -> [ untyped, untyped ]
|
|
60
61
|
|
|
61
|
-
#
|
|
62
|
-
|
|
62
|
+
# A string is read as JSON; anything else, or JSON that is neither an
|
|
63
|
+
# object nor an array, is left for #call to decline.
|
|
64
|
+
# : (untyped) -> untyped
|
|
65
|
+
def structure: (untyped) -> untyped
|
|
63
66
|
|
|
64
67
|
# : (Hash[untyped, untyped], Hash[untyped, untyped], Array[String], nested_changes) -> void
|
|
65
68
|
def walk: (Hash[untyped, untyped], Hash[untyped, untyped], Array[String], nested_changes) -> void
|
|
@@ -6,11 +6,10 @@ module PaperTrailDiff
|
|
|
6
6
|
# the only place allowed to know about both PaperTrail and the pure engine.
|
|
7
7
|
# Reconstruction logic lives in the collaborators it wires together.
|
|
8
8
|
class PaperTrailAdapter
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def initialize: (associations: Array[String | Symbol], ignore: ignore_option, ?reload_live_endpoints: bool, ?allow_expensive: bool) -> void
|
|
9
|
+
# `recorded_changes:` reads what each activity boundary's version recorded.
|
|
10
|
+
# `allow_approximate:` accepts association paths read with PT-AT.
|
|
11
|
+
# : (associations: association_option, ignore: ignore_option, ?reload_live_endpoints: bool, ?recorded_changes: bool, ?allow_approximate: bool) -> void
|
|
12
|
+
def initialize: (associations: association_option, ignore: ignore_option, ?reload_live_endpoints: bool, ?recorded_changes: bool, ?allow_approximate: bool) -> void
|
|
14
13
|
|
|
15
14
|
# : (untyped, untyped) -> Diff
|
|
16
15
|
def compare: (untyped, untyped) -> Diff
|
|
@@ -19,44 +18,49 @@ module PaperTrailDiff
|
|
|
19
18
|
# : (Array[comparison_input]) -> comparison_results
|
|
20
19
|
def compare_many: (Array[comparison_input]) -> comparison_results
|
|
21
20
|
|
|
22
|
-
# : (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped
|
|
23
|
-
def timeline: (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped
|
|
21
|
+
# : (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped) -> Array[Step]
|
|
22
|
+
def timeline: (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped) -> Array[Step]
|
|
24
23
|
|
|
25
|
-
# : (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped, ?
|
|
26
|
-
def activity_timeline: (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped, ?
|
|
24
|
+
# : (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?) -> Array[ActivityStep]
|
|
25
|
+
def activity_timeline: (untyped, from: untyped, to: untyped, within: untyped, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?) -> Array[ActivityStep]
|
|
27
26
|
|
|
28
|
-
# : (untyped, from: untyped, to: untyped, within: untyped, ?activity: bool, ?version_scope: untyped, ?
|
|
29
|
-
def analyze: (untyped, from: untyped, to: untyped, within: untyped, ?activity: bool, ?version_scope: untyped, ?
|
|
27
|
+
# : (untyped, from: untyped, to: untyped, within: untyped, ?activity: bool, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?) -> Analysis
|
|
28
|
+
def analyze: (untyped, from: untyped, to: untyped, within: untyped, ?activity: bool, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?) -> Analysis
|
|
30
29
|
|
|
31
30
|
# Analyzes many roots over one shared range, preparing their history once.
|
|
32
|
-
# : (Array[untyped], within: untyped, ?activity: bool, ?version_scope: untyped, ?
|
|
33
|
-
def analyze_many: (Array[untyped], within: untyped, ?activity: bool, ?version_scope: untyped, ?
|
|
31
|
+
# : (Array[untyped], within: untyped, ?activity: bool, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?) -> Hash[identity, Analysis]
|
|
32
|
+
def analyze_many: (Array[untyped], within: untyped, ?activity: bool, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?) -> Hash[identity, Analysis]
|
|
34
33
|
|
|
35
34
|
# Selects the roots from a relation before running the ordinary batch, so a
|
|
36
35
|
# caller reporting on a population does not have to rediscover which of its
|
|
37
36
|
# members changed. The roots the relation could not reach come back named
|
|
38
37
|
# rather than dropped -- see `PaperTrailDiff.analyze_scope`.
|
|
39
|
-
# : (untyped, limit: Integer?, within: untyped, ?activity: bool, ?version_scope: untyped, ?
|
|
40
|
-
def analyze_scope: (untyped, limit: Integer?, within: untyped, ?activity: bool, ?version_scope: untyped, ?
|
|
38
|
+
# : (untyped, limit: Integer?, within: untyped, ?activity: bool, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?, ?historical_filter: untyped, ?max_filter_versions: Integer, ?include_deleted: bool) -> ScopedAnalysis
|
|
39
|
+
def analyze_scope: (untyped, limit: Integer?, within: untyped, ?activity: bool, ?version_scope: untyped, ?snapshots: bool, ?group: Symbol?, ?historical_filter: untyped, ?max_filter_versions: Integer, ?include_deleted: bool) -> ScopedAnalysis
|
|
41
40
|
|
|
42
41
|
private
|
|
43
42
|
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
# : (bool, bool, Symbol?) -> ActivityView
|
|
44
|
+
def activity_view: (bool, bool, Symbol?) -> ActivityView
|
|
45
|
+
|
|
46
|
+
# : (untyped) -> Hash[Symbol, untyped]
|
|
47
|
+
def model_payload: (untyped) -> Hash[Symbol, untyped]
|
|
48
|
+
|
|
49
|
+
# : (Array[untyped], within: untyped, activity: bool, version_scope: untyped, view: ActivityView) -> Hash[identity, Analysis]
|
|
50
|
+
def analyze_batch: (Array[untyped], within: untyped, activity: bool, version_scope: untyped, view: ActivityView) -> Hash[identity, Analysis]
|
|
51
|
+
|
|
52
|
+
# Analysis reads association history, so a request it would refuse is
|
|
53
|
+
# refused before the first selection query rather than once analysis starts.
|
|
54
|
+
# : (untyped) -> void
|
|
55
|
+
def check_scope: (untyped) -> void
|
|
48
56
|
|
|
49
57
|
# : (Array[comparison_input], preparer: untyped) -> ComparisonBatch
|
|
50
58
|
def comparison_batch: (Array[comparison_input], preparer: untyped) -> ComparisonBatch
|
|
51
59
|
|
|
60
|
+
# Refused before the current records load, rather than once analysis starts.
|
|
52
61
|
# : (Array[untyped]) -> Hash[identity, untyped]
|
|
53
62
|
def load_batch_endpoints: (Array[untyped]) -> Hash[identity, untyped]
|
|
54
63
|
|
|
55
|
-
# : (untyped, historical: bool) -> void
|
|
56
|
-
def prepare_batch_model: (untyped, historical: bool) -> void
|
|
57
|
-
|
|
58
|
-
@batch_safety: BatchSafety
|
|
59
|
-
|
|
60
64
|
# : (untyped, Array[Array[String]], Hash[Symbol, untyped]) -> Hash[Array[String], Analysis?]
|
|
61
65
|
def analyze_deleted: (untyped, Array[Array[String]], Hash[Symbol, untyped]) -> Hash[Array[String], Analysis?]
|
|
62
66
|
|
|
@@ -74,6 +78,8 @@ module PaperTrailDiff
|
|
|
74
78
|
|
|
75
79
|
@normalizer: SnapshotNormalizer
|
|
76
80
|
|
|
81
|
+
@recorded: IgnorePolicy?
|
|
82
|
+
|
|
77
83
|
@snapshot_pool: SnapshotPool
|
|
78
84
|
|
|
79
85
|
@timeline_snapshotter: TimelineSnapshotProvider
|
|
@@ -82,24 +88,19 @@ module PaperTrailDiff
|
|
|
82
88
|
|
|
83
89
|
@traversal_preparer: TraversalPreparer
|
|
84
90
|
|
|
85
|
-
#
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
#
|
|
89
|
-
# cannot be told apart and any association change between them is invisible.
|
|
90
|
-
# The result may still be correct -- nothing associated may have changed --
|
|
91
|
-
# and the gem cannot tell which, since not seeing the change is the symptom.
|
|
92
|
-
# So it reports the condition and leaves the judgement to the application.
|
|
91
|
+
# The result may still be correct -- nothing the path reaches may have
|
|
92
|
+
# changed -- and the gem cannot tell which, since not seeing the change is
|
|
93
|
+
# the symptom. So it reports the condition and leaves the judgement to the
|
|
94
|
+
# application.
|
|
93
95
|
# : (untyped, untyped) -> void
|
|
94
96
|
def notify_ambiguous_association_boundary: (untyped, untyped) -> void
|
|
95
97
|
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
def close_on_current?: (Symbol?, untyped) -> bool
|
|
98
|
+
# Loaded history orders two versions that share a timestamp by id, but
|
|
99
|
+
# PT-AT places association changes by timestamp alone, so only a path it
|
|
100
|
+
# reads can lose a change between them. A request the preparer refuses
|
|
101
|
+
# raises here, before anything is reported.
|
|
102
|
+
# : (untyped, untyped) -> bool
|
|
103
|
+
def ambiguous_association_boundary?: (untyped, untyped) -> bool
|
|
103
104
|
|
|
104
105
|
# With neither a window nor endpoints, a range is the record's whole
|
|
105
106
|
# history through its current saved state; a missing endpoint takes that
|
|
@@ -107,26 +108,30 @@ module PaperTrailDiff
|
|
|
107
108
|
# : (untyped, untyped, untyped, untyped) -> [untyped, untyped]
|
|
108
109
|
def default_range: (untyped, untyped, untyped, untyped) -> [ untyped, untyped ]
|
|
109
110
|
|
|
111
|
+
# A window with nothing recorded after its last change ends at the live
|
|
112
|
+
# record, which holds the state that change produced -- whether the window
|
|
113
|
+
# ended a moment ago or long before. Explicit endpoints name their own end.
|
|
110
114
|
# Only a saved row has current state to close on. A destroyed root's own
|
|
111
115
|
# destroy version already terminates its history, and a reified or unsaved
|
|
112
116
|
# instance stands for a state that is not in the table.
|
|
113
|
-
# : (untyped,
|
|
114
|
-
def live_endpoint_for: (untyped,
|
|
117
|
+
# : (untyped, untyped) -> untyped
|
|
118
|
+
def live_endpoint_for: (untyped, untyped) -> untyped
|
|
115
119
|
|
|
116
120
|
# : () -> void
|
|
117
121
|
def build_snapshotters: () -> void
|
|
118
122
|
|
|
119
|
-
# : (bool, within: untyped,
|
|
120
|
-
def batched_root_analyzer: (bool, within: untyped,
|
|
123
|
+
# : (bool, within: untyped, view: ActivityView) -> BatchedRootAnalyzer
|
|
124
|
+
def batched_root_analyzer: (bool, within: untyped, view: ActivityView) -> BatchedRootAnalyzer
|
|
121
125
|
|
|
122
126
|
# : () -> HistoricalSnapshotStore
|
|
123
127
|
def build_historical_store: () -> HistoricalSnapshotStore
|
|
124
128
|
|
|
125
|
-
#
|
|
126
|
-
|
|
129
|
+
# Refreshes one root's snapshots, reading with the history prepared for it.
|
|
130
|
+
# : (PreparedActivitySnapshots) -> BranchSnapshotRefresher
|
|
131
|
+
def branch_refresher: (PreparedActivitySnapshots) -> BranchSnapshotRefresher
|
|
127
132
|
|
|
128
|
-
# : (untyped, from: untyped, to: untyped, within: untyped,
|
|
129
|
-
def activity_builder: (untyped, from: untyped, to: untyped, within: untyped,
|
|
133
|
+
# : (untyped, from: untyped, to: untyped, within: untyped, version_scope: untyped, live_endpoint: untyped, view: ActivityView) -> ActivityTimelineBuilder
|
|
134
|
+
def activity_builder: (untyped, from: untyped, to: untyped, within: untyped, version_scope: untyped, live_endpoint: untyped, view: ActivityView) -> ActivityTimelineBuilder
|
|
130
135
|
|
|
131
136
|
# : (untyped) -> RecordSnapshot?
|
|
132
137
|
def snapshot_for_endpoint: (untyped) -> RecordSnapshot?
|
|
@@ -134,11 +139,8 @@ module PaperTrailDiff
|
|
|
134
139
|
# : (untyped) -> RecordSnapshot?
|
|
135
140
|
def historical_snapshot: (untyped) -> RecordSnapshot?
|
|
136
141
|
|
|
137
|
-
# : (untyped) -> RecordSnapshot?
|
|
138
|
-
def
|
|
139
|
-
|
|
140
|
-
# : (untyped, untyped) -> RecordSnapshot?
|
|
141
|
-
def snapshot_at: (untyped, untyped) -> RecordSnapshot?
|
|
142
|
+
# : (untyped, untyped, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
143
|
+
def snapshot_at: (untyped, untyped, ?history: PreparedHistory?) -> RecordSnapshot?
|
|
142
144
|
|
|
143
145
|
# : (untyped) -> RecordSnapshot
|
|
144
146
|
def live_snapshot: (untyped) -> RecordSnapshot
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Generated from lib/paper_trail_diff/preloaded_endpoint_batch_loader.rb with RBS::Inline
|
|
2
2
|
|
|
3
3
|
module PaperTrailDiff
|
|
4
|
-
# Validates and reuses caller-owned live records
|
|
4
|
+
# Validates and reuses caller-owned live records, reading again only the
|
|
5
|
+
# associations a preload of many records cannot have loaded correctly.
|
|
5
6
|
class PreloadedEndpointBatchLoader
|
|
6
7
|
# : (tree: AssociationTree, traversal: AssociationTraversal) -> void
|
|
7
8
|
def initialize: (tree: AssociationTree, traversal: AssociationTraversal) -> void
|
|
@@ -20,5 +21,12 @@ module PaperTrailDiff
|
|
|
20
21
|
|
|
21
22
|
# : (untyped, AssociationTree, String, untyped) -> void
|
|
22
23
|
def validate_association: (untyped, AssociationTree, String, untyped) -> void
|
|
24
|
+
|
|
25
|
+
# Preloading many records applies a limit or offset to all of them
|
|
26
|
+
# together, so what a caller preloaded cannot be trusted: one record keeps
|
|
27
|
+
# another's share, or none. Such an association is read again for each
|
|
28
|
+
# record, as reloading reads it.
|
|
29
|
+
# : (untyped) -> void
|
|
30
|
+
def read_alone: (untyped) -> void
|
|
23
31
|
end
|
|
24
32
|
end
|
|
@@ -74,6 +74,11 @@ module PaperTrailDiff
|
|
|
74
74
|
# : (Hash[Symbol, untyped], untyped) -> Array[untyped]
|
|
75
75
|
def child_ids_for: (Hash[Symbol, untyped], untyped) -> Array[untyped]
|
|
76
76
|
|
|
77
|
+
# PT-AT records a checkpoint's membership as it is when the checkpoint is
|
|
78
|
+
# saved, so a tag attached earlier in the checkpoint's own transaction is a
|
|
79
|
+
# member there, unlike other associations, which a version reads as they
|
|
80
|
+
# were before its transaction. A member created in that transaction has no
|
|
81
|
+
# earlier state, so it is read as it was created.
|
|
77
82
|
# : (untyped, untyped, untyped, untyped, bool) -> Array[untyped]?
|
|
78
83
|
def habtm_records: (untyped, untyped, untyped, untyped, bool) -> Array[untyped]?
|
|
79
84
|
|
|
@@ -68,6 +68,12 @@ module PaperTrailDiff
|
|
|
68
68
|
# : (untyped) -> untyped
|
|
69
69
|
def record_before: (untyped) -> untyped
|
|
70
70
|
|
|
71
|
+
# A record created in the boundary's own transaction has no state before
|
|
72
|
+
# it, yet a HABTM checkpoint saved later in that transaction records it as
|
|
73
|
+
# a member. Such a member is read as it was created.
|
|
74
|
+
# : (untyped) -> untyped
|
|
75
|
+
def record_created_in: (untyped) -> untyped
|
|
76
|
+
|
|
71
77
|
# : (untyped) -> PreparedRecordState?
|
|
72
78
|
def state_before: (untyped) -> PreparedRecordState?
|
|
73
79
|
|
|
@@ -90,8 +96,8 @@ module PaperTrailDiff
|
|
|
90
96
|
# : (untyped) -> Array[PreparedRecordState]
|
|
91
97
|
def states_around: (untyped) -> Array[PreparedRecordState]
|
|
92
98
|
|
|
93
|
-
# : (untyped) -> [
|
|
94
|
-
def transition: (untyped) -> [
|
|
99
|
+
# : (untyped) -> [PreparedRecordState, PreparedRecordState]?
|
|
100
|
+
def transition: (untyped) -> [ PreparedRecordState, PreparedRecordState ]?
|
|
95
101
|
|
|
96
102
|
private
|
|
97
103
|
|
|
@@ -144,9 +150,15 @@ module PaperTrailDiff
|
|
|
144
150
|
# : (untyped, untyped, untyped) -> untyped
|
|
145
151
|
def record_before: (untyped, untyped, untyped) -> untyped
|
|
146
152
|
|
|
153
|
+
# : (untyped, untyped, untyped) -> untyped
|
|
154
|
+
def record_created_in: (untyped, untyped, untyped) -> untyped
|
|
155
|
+
|
|
147
156
|
# : (untyped, untyped, untyped) -> [bool, PreparedRecordState?]
|
|
148
157
|
def snapshot_state_before: (untyped, untyped, untyped) -> [ bool, PreparedRecordState? ]
|
|
149
158
|
|
|
159
|
+
# Typed as a reified record's attributes are. A JSON or JSONB `object`
|
|
160
|
+
# column stores times and dates as strings, which PaperTrail does not cast
|
|
161
|
+
# back, and the transition is carried into snapshots built from records.
|
|
150
162
|
# : (untyped, untyped, untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?
|
|
151
163
|
def transition: (untyped, untyped, untyped) -> [ Hash[untyped, untyped], Hash[untyped, untyped] ]?
|
|
152
164
|
|
|
@@ -173,6 +185,11 @@ module PaperTrailDiff
|
|
|
173
185
|
|
|
174
186
|
private
|
|
175
187
|
|
|
188
|
+
# A model whose records need their own initialization is cast by
|
|
189
|
+
# instantiating it, as reify does.
|
|
190
|
+
# : (PreparedRecordState) -> Hash[untyped, untyped]
|
|
191
|
+
def typed_attributes: (PreparedRecordState) -> Hash[untyped, untyped]
|
|
192
|
+
|
|
176
193
|
# : (untyped, String) -> bool
|
|
177
194
|
def generated_reader?: (untyped, String) -> bool
|
|
178
195
|
|
|
@@ -13,6 +13,8 @@ module PaperTrailDiff
|
|
|
13
13
|
# An error is a specification, so it names the way out as well as the wall.
|
|
14
14
|
# A window ending at the present can never gain a later version, which makes
|
|
15
15
|
# "write a checkpoint afterwards" impossible advice on its own.
|
|
16
|
+
# A window closes on the current record when it reaches the present, so
|
|
17
|
+
# this is raised only when there is none to read.
|
|
16
18
|
INCOMPLETE: ::String
|
|
17
19
|
|
|
18
20
|
# : (in_range: Array[untyped], selected: Array[untyped], after_range: untyped, windowed: bool, ?context_required: bool, ?filtered: bool, ?live_endpoint: untyped) -> void
|
|
@@ -13,6 +13,9 @@ module PaperTrailDiff
|
|
|
13
13
|
# ranking alone.
|
|
14
14
|
RELATION_VALUES: untyped
|
|
15
15
|
|
|
16
|
+
# Relation parts that load or shape rows without choosing them.
|
|
17
|
+
LOADING_VALUES: untyped
|
|
18
|
+
|
|
16
19
|
# Types whose stored values compare in Ruby as the database compares them,
|
|
17
20
|
# named rather than referenced so that loading needs no Active Model.
|
|
18
21
|
VALUE_TYPES: untyped
|
|
@@ -47,6 +50,15 @@ module PaperTrailDiff
|
|
|
47
50
|
# : (untyped, ?untyped, ?ranked: bool) -> ScopeCondition?
|
|
48
51
|
def self.build: (untyped, ?untyped, ?ranked: bool) -> ScopeCondition?
|
|
49
52
|
|
|
53
|
+
# A relation's own where clause, default scope included, read as
|
|
54
|
+
# conditions on stored attributes; nil when it cannot be. Its order,
|
|
55
|
+
# limit, and offset choose a page of current rows rather than membership,
|
|
56
|
+
# and loading or selecting columns changes neither, so they are left out.
|
|
57
|
+
# A single-table subclass's type condition is left to the caller, as for
|
|
58
|
+
# an association.
|
|
59
|
+
# : (untyped, untyped) -> ScopeCondition?
|
|
60
|
+
def self.for_relation: (untyped, untyped) -> ScopeCondition?
|
|
61
|
+
|
|
50
62
|
# nil when the relation picks its members by conditions alone.
|
|
51
63
|
# : (untyped, untyped, untyped) -> ScopeRanking?
|
|
52
64
|
def self.ranking: (untyped, untyped, untyped) -> ScopeRanking?
|
|
@@ -78,6 +90,8 @@ module PaperTrailDiff
|
|
|
78
90
|
# : (untyped, Array[untyped], ?ScopeRanking?) -> void
|
|
79
91
|
def initialize: (untyped, Array[untyped], ?ScopeRanking?) -> void
|
|
80
92
|
|
|
93
|
+
# SQL admits a row only when its condition is true, not when it is
|
|
94
|
+
# unknown.
|
|
81
95
|
# : (Hash[String, untyped]) -> bool
|
|
82
96
|
def matches?: (Hash[String, untyped]) -> bool
|
|
83
97
|
|
|
@@ -91,8 +105,10 @@ module PaperTrailDiff
|
|
|
91
105
|
# : (Array[untyped]) -> Array[untyped]
|
|
92
106
|
def rank: (Array[untyped]) -> Array[untyped]
|
|
93
107
|
|
|
94
|
-
# SQL
|
|
95
|
-
# with nil,
|
|
108
|
+
# SQL's three values: a comparison with NULL is unknown (nil) rather than
|
|
109
|
+
# false, except an IS NULL or IS NOT NULL test, an equality with nil, which
|
|
110
|
+
# is always known. Unknown matters only under NOT, which leaves it
|
|
111
|
+
# unknown where false would become true.
|
|
96
112
|
COMPARISONS: untyped
|
|
97
113
|
|
|
98
114
|
private
|
|
@@ -103,8 +119,20 @@ module PaperTrailDiff
|
|
|
103
119
|
|
|
104
120
|
@ranking: ScopeRanking?
|
|
105
121
|
|
|
106
|
-
#
|
|
107
|
-
|
|
122
|
+
# true, false, or nil for unknown.
|
|
123
|
+
# : (Array[untyped], Hash[String, untyped]) -> bool?
|
|
124
|
+
def evaluate: (Array[untyped], Hash[String, untyped]) -> bool?
|
|
125
|
+
|
|
126
|
+
# False if any part is, otherwise unknown if any part is.
|
|
127
|
+
# : (Array[bool?]) -> bool?
|
|
128
|
+
def all: (Array[bool?]) -> bool?
|
|
129
|
+
|
|
130
|
+
# True if any part is, otherwise unknown if any part is.
|
|
131
|
+
# : (Array[bool?]) -> bool?
|
|
132
|
+
def any: (Array[bool?]) -> bool?
|
|
133
|
+
|
|
134
|
+
# : (bool?) -> bool?
|
|
135
|
+
def negate: (bool?) -> bool?
|
|
108
136
|
|
|
109
137
|
# The form the database holds, as the scope's own values were cast.
|
|
110
138
|
# : (String, Hash[String, untyped]) -> untyped
|
|
@@ -146,6 +174,7 @@ module PaperTrailDiff
|
|
|
146
174
|
# : (untyped) -> Array[untyped]
|
|
147
175
|
def comparison: (untyped) -> Array[untyped]
|
|
148
176
|
|
|
177
|
+
# Whether a value is NULL compares alike on every type.
|
|
149
178
|
# : (Symbol, untyped) -> Array[untyped]
|
|
150
179
|
def binary: (Symbol, untyped) -> Array[untyped]
|
|
151
180
|
|
|
@@ -158,12 +187,17 @@ module PaperTrailDiff
|
|
|
158
187
|
def list: (Symbol, untyped, Array[untyped]) -> Array[untyped]
|
|
159
188
|
|
|
160
189
|
# Ruby comparison stands in for SQL only on the record's own column of
|
|
161
|
-
# a type both compare alike.
|
|
162
|
-
#
|
|
163
|
-
|
|
190
|
+
# a type both compare alike. Whether a value is NULL, any column's
|
|
191
|
+
# type compares alike.
|
|
192
|
+
# : (untyped, ?null_test: bool) -> String
|
|
193
|
+
def column: (untyped, ?null_test: bool) -> String
|
|
194
|
+
|
|
195
|
+
# : (String, untyped) -> bool
|
|
196
|
+
def comparable?: (String, untyped) -> bool
|
|
164
197
|
|
|
165
|
-
#
|
|
166
|
-
|
|
198
|
+
# PostgreSQL's citext is text that compares without regard to case.
|
|
199
|
+
# : (untyped) -> bool
|
|
200
|
+
def exact_text?: (untyped) -> bool
|
|
167
201
|
|
|
168
202
|
# An enum compares the values it stores, which its subtype describes. A
|
|
169
203
|
# wrapper such as a serialized or encrypted type is none of these.
|
|
@@ -13,6 +13,10 @@ module PaperTrailDiff
|
|
|
13
13
|
|
|
14
14
|
ENUM_TYPE: ::String
|
|
15
15
|
|
|
16
|
+
# Rails wraps a time-zone-aware attribute's type, by default every
|
|
17
|
+
# datetime's, in this delegator; the time it stores is the wrapped type's.
|
|
18
|
+
TIME_ZONE_TYPE: ::String
|
|
19
|
+
|
|
16
20
|
# Integers, booleans and dates sort alike everywhere. Strings follow a
|
|
17
21
|
# collation, so they are not read.
|
|
18
22
|
ORDER_TYPES: untyped
|
|
@@ -67,6 +71,10 @@ module PaperTrailDiff
|
|
|
67
71
|
# : (untyped, String) -> bool
|
|
68
72
|
def self.orderable?: (untyped, String) -> bool
|
|
69
73
|
|
|
74
|
+
# The type of the value a column stores, under an enum or time zone wrapper.
|
|
75
|
+
# : (untyped) -> untyped
|
|
76
|
+
def self.stored_type: (untyped) -> untyped
|
|
77
|
+
|
|
70
78
|
# Active Record truncates a time to its column's precision before writing
|
|
71
79
|
# it, so history holds the stored value when it keeps that many digits.
|
|
72
80
|
# Times the type stores in UTC sort as the instants they name; local
|
|
@@ -29,6 +29,12 @@ module PaperTrailDiff
|
|
|
29
29
|
# : (analyses: Hash[Array[String], Analysis], unreachable: Array[Array[String]], ?roots: Array[untyped], ?deleted: Hash[Array[String], Analysis?]) -> void
|
|
30
30
|
def initialize: (analyses: Hash[Array[String], Analysis], unreachable: Array[Array[String]], ?roots: Array[untyped], ?deleted: Hash[Array[String], Analysis?]) -> void
|
|
31
31
|
|
|
32
|
+
# Each root's change rows, keyed as `analyses` is: the roots that still
|
|
33
|
+
# exist, then the deleted ones that have history to report. A deleted root
|
|
34
|
+
# without destroy history has no rows and is left out.
|
|
35
|
+
# : () -> Hash[Array[String], Array[ChangeRow]]
|
|
36
|
+
def change_rows: () -> Hash[Array[String], Array[ChangeRow]]
|
|
37
|
+
|
|
32
38
|
# Two elements, not three: `roots` is reached by name so that existing
|
|
33
39
|
# destructuring keeps working.
|
|
34
40
|
# : () -> [Hash[Array[String], Analysis], Array[Array[String]]]
|
|
@@ -9,11 +9,16 @@ module PaperTrailDiff
|
|
|
9
9
|
# : () -> ScopedAnalysis
|
|
10
10
|
def call: () -> ScopedAnalysis
|
|
11
11
|
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
# : (ScopedRootSelection::Result, Array[Array[String]], Hash[Array[String], Analysis?]) -> ScopedAnalysis
|
|
15
|
+
def analysis: (ScopedRootSelection::Result, Array[Array[String]], Hash[Array[String], Analysis?]) -> ScopedAnalysis
|
|
16
|
+
|
|
12
17
|
@analyzer: untyped
|
|
13
18
|
|
|
14
19
|
@deleted_analyzer: untyped
|
|
15
20
|
|
|
16
|
-
@
|
|
21
|
+
@deleted_filter: DeletedRootFilter?
|
|
17
22
|
|
|
18
23
|
@limit: Integer
|
|
19
24
|
|
|
@@ -71,6 +71,12 @@ module PaperTrailDiff
|
|
|
71
71
|
# : (Array[AssociationActivitySelection::source]) -> Array[AssociationActivitySelection::Query]?
|
|
72
72
|
def subqueries: (Array[AssociationActivitySelection::source]) -> Array[AssociationActivitySelection::Query]?
|
|
73
73
|
|
|
74
|
+
# Which candidates still have a row is asked without the relation's
|
|
75
|
+
# conditions, so that "filtered out" and "no longer exists" stay
|
|
76
|
+
# separable. A filter then reads the history of the relation's records
|
|
77
|
+
# only, whose order and page choose among those that match, and of the
|
|
78
|
+
# deleted ones, which no relation can test. Those it lists, as without a
|
|
79
|
+
# filter, but does not count toward `limit:`.
|
|
74
80
|
# : (Array[String]) -> Result
|
|
75
81
|
def plucked_selection: (Array[String]) -> Result
|
|
76
82
|
|
|
@@ -113,10 +119,8 @@ module PaperTrailDiff
|
|
|
113
119
|
# : () -> Array[String]
|
|
114
120
|
def versioned_ids: () -> Array[String]
|
|
115
121
|
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
# : (Array[String]) -> Array[String]
|
|
119
|
-
def live_ids: (Array[String]) -> Array[String]
|
|
122
|
+
# : (untyped, Array[String]) -> Array[String]
|
|
123
|
+
def ids_in: (untyped, Array[String]) -> Array[String]
|
|
120
124
|
|
|
121
125
|
# Deduplicate records rather than adding SQL DISTINCT: an otherwise valid
|
|
122
126
|
# relation may order by joined columns or select a PostgreSQL json column.
|