paper_trail_diff 0.3.0 → 0.4.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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/README.md +269 -30
  4. data/lib/paper_trail_diff/activity_belongs_to_event_applier.rb +126 -0
  5. data/lib/paper_trail_diff/activity_boundary.rb +21 -0
  6. data/lib/paper_trail_diff/activity_collection_event_applier.rb +137 -0
  7. data/lib/paper_trail_diff/activity_collection_record_updater.rb +67 -0
  8. data/lib/paper_trail_diff/activity_collection_route_change.rb +21 -0
  9. data/lib/paper_trail_diff/activity_collection_route_updater.rb +128 -0
  10. data/lib/paper_trail_diff/activity_event_record_normalizer.rb +42 -0
  11. data/lib/paper_trail_diff/activity_event_record_resolver.rb +120 -0
  12. data/lib/paper_trail_diff/activity_event_route_finder.rb +92 -0
  13. data/lib/paper_trail_diff/activity_event_snapshot_refresher.rb +56 -650
  14. data/lib/paper_trail_diff/activity_relationship.rb +55 -0
  15. data/lib/paper_trail_diff/activity_root_steps.rb +27 -0
  16. data/lib/paper_trail_diff/activity_snapshot_sequence.rb +8 -3
  17. data/lib/paper_trail_diff/activity_timeline_builder.rb +47 -32
  18. data/lib/paper_trail_diff/analysis.rb +9 -0
  19. data/lib/paper_trail_diff/branch_snapshot_refresher.rb +2 -0
  20. data/lib/paper_trail_diff/collection_comparator.rb +14 -1
  21. data/lib/paper_trail_diff/collection_transition.rb +6 -3
  22. data/lib/paper_trail_diff/endpoint.rb +27 -2
  23. data/lib/paper_trail_diff/errors.rb +3 -0
  24. data/lib/paper_trail_diff/historical_association_reifier.rb +8 -5
  25. data/lib/paper_trail_diff/historical_snapshot_store.rb +9 -2
  26. data/lib/paper_trail_diff/prepared_association_reifier.rb +8 -5
  27. data/lib/paper_trail_diff/prepared_edge_loader.rb +6 -4
  28. data/lib/paper_trail_diff/prepared_history_loader.rb +3 -2
  29. data/lib/paper_trail_diff/prepared_record_index.rb +90 -15
  30. data/lib/paper_trail_diff/snapshot.rb +26 -0
  31. data/lib/paper_trail_diff/snapshot_normalizer.rb +14 -2
  32. data/lib/paper_trail_diff/time_activity_timeline_builder.rb +52 -32
  33. data/lib/paper_trail_diff/time_version_range.rb +11 -0
  34. data/lib/paper_trail_diff/timeline_range.rb +57 -4
  35. data/lib/paper_trail_diff/version.rb +1 -1
  36. data/lib/paper_trail_diff/version_association_candidate_scope.rb +46 -19
  37. data/lib/paper_trail_diff.rb +10 -0
  38. data/sig/generated/paper_trail_diff/activity_belongs_to_event_applier.rbs +41 -0
  39. data/sig/generated/paper_trail_diff/activity_boundary.rbs +9 -0
  40. data/sig/generated/paper_trail_diff/activity_collection_event_applier.rbs +46 -0
  41. data/sig/generated/paper_trail_diff/activity_collection_record_updater.rbs +25 -0
  42. data/sig/generated/paper_trail_diff/activity_collection_route_change.rbs +17 -0
  43. data/sig/generated/paper_trail_diff/activity_collection_route_updater.rbs +44 -0
  44. data/sig/generated/paper_trail_diff/activity_event_record_normalizer.rbs +19 -0
  45. data/sig/generated/paper_trail_diff/activity_event_record_resolver.rbs +44 -0
  46. data/sig/generated/paper_trail_diff/activity_event_route_finder.rbs +47 -0
  47. data/sig/generated/paper_trail_diff/activity_event_snapshot_refresher.rbs +18 -110
  48. data/sig/generated/paper_trail_diff/activity_relationship.rbs +23 -0
  49. data/sig/generated/paper_trail_diff/activity_root_steps.rbs +13 -0
  50. data/sig/generated/paper_trail_diff/activity_snapshot_sequence.rbs +2 -2
  51. data/sig/generated/paper_trail_diff/activity_timeline_builder.rbs +20 -10
  52. data/sig/generated/paper_trail_diff/analysis.rbs +5 -0
  53. data/sig/generated/paper_trail_diff/collection_comparator.rbs +7 -0
  54. data/sig/generated/paper_trail_diff/collection_transition.rbs +4 -1
  55. data/sig/generated/paper_trail_diff/endpoint.rbs +12 -0
  56. data/sig/generated/paper_trail_diff/errors.rbs +4 -0
  57. data/sig/generated/paper_trail_diff/historical_association_reifier.rbs +1 -1
  58. data/sig/generated/paper_trail_diff/historical_snapshot_store.rbs +2 -2
  59. data/sig/generated/paper_trail_diff/prepared_association_reifier.rbs +1 -1
  60. data/sig/generated/paper_trail_diff/prepared_edge_loader.rbs +1 -0
  61. data/sig/generated/paper_trail_diff/prepared_history_loader.rbs +2 -2
  62. data/sig/generated/paper_trail_diff/prepared_record_index.rbs +39 -6
  63. data/sig/generated/paper_trail_diff/snapshot.rbs +20 -0
  64. data/sig/generated/paper_trail_diff/snapshot_normalizer.rbs +8 -0
  65. data/sig/generated/paper_trail_diff/time_activity_timeline_builder.rbs +21 -10
  66. data/sig/generated/paper_trail_diff/time_version_range.rbs +7 -0
  67. data/sig/generated/paper_trail_diff/timeline_range.rbs +29 -0
  68. data/sig/generated/paper_trail_diff/version_association_candidate_scope.rbs +17 -4
  69. metadata +24 -4
@@ -0,0 +1,41 @@
1
+ # Generated from lib/paper_trail_diff/activity_belongs_to_event_applier.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Applies selected non-polymorphic belongs-to target updates to a snapshot.
5
+ class ActivityBelongsToEventApplier
6
+ # : (route_finder: ActivityEventRouteFinder, record_resolver: ActivityEventRecordResolver, record_normalizer: ActivityEventRecordNormalizer) -> void
7
+ def initialize: (route_finder: ActivityEventRouteFinder, record_resolver: ActivityEventRecordResolver, record_normalizer: ActivityEventRecordNormalizer) -> void
8
+
9
+ # : (untyped, untyped, RecordSnapshot, AssociationTree, SnapshotNormalizer, untyped) -> [bool, RecordSnapshot?]
10
+ def call: (untyped, untyped, RecordSnapshot, AssociationTree, SnapshotNormalizer, untyped) -> [ bool, RecordSnapshot? ]
11
+
12
+ private
13
+
14
+ @record_normalizer: ActivityEventRecordNormalizer
15
+
16
+ @record_resolver: ActivityEventRecordResolver
17
+
18
+ @route_finder: ActivityEventRouteFinder
19
+
20
+ # : (Array[untyped], untyped, SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
21
+ def normalized_route_record: (Array[untyped], untyped, SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
22
+
23
+ # : (RecordSnapshot, Array[untyped], untyped, RecordSnapshot?, ?depth: Integer) -> [RecordSnapshot, bool]
24
+ def replace_route: (RecordSnapshot, Array[untyped], untyped, RecordSnapshot?, ?depth: Integer) -> [ RecordSnapshot, bool ]
25
+
26
+ # : (Array[RecordSnapshot], Array[untyped], untyped, RecordSnapshot?, Integer) -> [Array[RecordSnapshot], bool]
27
+ def replacement_records: (Array[RecordSnapshot], Array[untyped], untyped, RecordSnapshot?, Integer) -> [ Array[RecordSnapshot], bool ]
28
+
29
+ # : (Array[RecordSnapshot], untyped, RecordSnapshot?) -> [Array[RecordSnapshot], bool]
30
+ def replace_existing_target: (Array[RecordSnapshot], untyped, RecordSnapshot?) -> [ Array[RecordSnapshot], bool ]
31
+
32
+ # : (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
33
+ def replace_association: (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
34
+
35
+ # : (untyped, RecordSnapshot?) -> String
36
+ def replacement_type: (untyped, RecordSnapshot?) -> String
37
+
38
+ # : (untyped) -> untyped
39
+ def endpoint_model_class: (untyped) -> untyped
40
+ end
41
+ end
@@ -25,6 +25,12 @@ module PaperTrailDiff
25
25
  # : (untyped, captured_at: untyped) -> ActivityBoundary
26
26
  def self.current: (untyped, captured_at: untyped) -> ActivityBoundary
27
27
 
28
+ # The state a `destroy` version leaves behind. A version records the state
29
+ # before its own event, so the boundary built from a destroy version still
30
+ # holds the record; this one is the absence that follows it.
31
+ # : (untyped) -> ActivityBoundary
32
+ def self.destroyed: (untyped) -> ActivityBoundary
33
+
28
34
  # : (kind: Symbol, version_id: untyped, item_type: untyped, item_id: untyped, recorded_at: untyped, ?event: untyped, ?whodunnit: untyped) -> void
29
35
  def initialize: (kind: Symbol, version_id: untyped, item_type: untyped, item_id: untyped, recorded_at: untyped, ?event: untyped, ?whodunnit: untyped) -> void
30
36
 
@@ -34,6 +40,9 @@ module PaperTrailDiff
34
40
  # : () -> bool
35
41
  def current?: () -> bool
36
42
 
43
+ # : () -> bool
44
+ def destroyed?: () -> bool
45
+
37
46
  # : () -> Hash[Symbol, untyped]
38
47
  def to_h: () -> Hash[Symbol, untyped]
39
48
  end
@@ -0,0 +1,46 @@
1
+ # Generated from lib/paper_trail_diff/activity_collection_event_applier.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Applies a safe collection event across every selected route for its record type.
5
+ class ActivityCollectionEventApplier
6
+ # : (record_resolver: ActivityEventRecordResolver, record_normalizer: ActivityEventRecordNormalizer, route_updater: ActivityCollectionRouteUpdater, relationship: ActivityRelationship) -> void
7
+ def initialize: (record_resolver: ActivityEventRecordResolver, record_normalizer: ActivityEventRecordNormalizer, route_updater: ActivityCollectionRouteUpdater, relationship: ActivityRelationship) -> void
8
+
9
+ # : (Array[Array[untyped]], untyped, ActivitySnapshotDelta?) -> bool
10
+ def safe?: (Array[Array[untyped]], untyped, ActivitySnapshotDelta?) -> bool
11
+
12
+ # : (untyped, untyped, RecordSnapshot, SnapshotNormalizer, Array[Array[untyped]], untyped, ActivitySnapshotDelta?) -> [bool, RecordSnapshot]
13
+ def call: (untyped, untyped, RecordSnapshot, SnapshotNormalizer, Array[Array[untyped]], untyped, ActivitySnapshotDelta?) -> [ bool, RecordSnapshot ]
14
+
15
+ private
16
+
17
+ @record_normalizer: ActivityEventRecordNormalizer
18
+
19
+ @record_resolver: ActivityEventRecordResolver
20
+
21
+ @relationship: ActivityRelationship
22
+
23
+ @route_updater: ActivityCollectionRouteUpdater
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
27
+
28
+ # : (Array[Array[untyped]], untyped) -> bool
29
+ def unsafe_through_membership_event?: (Array[Array[untyped]], untyped) -> bool
30
+
31
+ # : (Array[Array[untyped]], ActivitySnapshotDelta?) -> bool
32
+ def unsafe_nested_membership_delta?: (Array[Array[untyped]], ActivitySnapshotDelta?) -> bool
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? ]
36
+
37
+ # : (untyped, Array[untyped], SnapshotNormalizer, Array[untyped]) -> RecordSnapshot?
38
+ def normalized_event_record: (untyped, Array[untyped], SnapshotNormalizer, Array[untyped]) -> RecordSnapshot?
39
+
40
+ # : (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?) -> RecordSnapshot?
41
+ def existing_delta_record: (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?) -> RecordSnapshot?
42
+
43
+ # : (RecordSnapshot, Array[untyped], ActivitySnapshotDelta) -> RecordSnapshot?
44
+ def nested_delta_owner: (RecordSnapshot, Array[untyped], ActivitySnapshotDelta) -> RecordSnapshot?
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ # Generated from lib/paper_trail_diff/activity_collection_record_updater.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Applies one event to the leaf records of a collection association snapshot.
5
+ class ActivityCollectionRecordUpdater
6
+ # : (ActivityRelationship) -> void
7
+ def initialize: (ActivityRelationship) -> void
8
+
9
+ # : (AssociationSnapshot, ActivityCollectionRouteChange, untyped, RecordSnapshot) -> RecordSnapshot?
10
+ def event_child: (AssociationSnapshot, ActivityCollectionRouteChange, untyped, RecordSnapshot) -> RecordSnapshot?
11
+
12
+ # : (AssociationSnapshot, untyped, RecordSnapshot?) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]
13
+ def call: (AssociationSnapshot, untyped, RecordSnapshot?) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]
14
+
15
+ # : (untyped, RecordSnapshot?) -> String
16
+ def replacement_type: (untyped, RecordSnapshot?) -> String
17
+
18
+ private
19
+
20
+ @relationship: ActivityRelationship
21
+
22
+ # : (Array[RecordSnapshot], Integer?, RecordSnapshot?) -> Array[RecordSnapshot]
23
+ def replacement_records: (Array[RecordSnapshot], Integer?, RecordSnapshot?) -> Array[RecordSnapshot]
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ # Generated from lib/paper_trail_diff/activity_collection_route_change.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Carries one collection event through recursive immutable route replacement.
5
+ class ActivityCollectionRouteChange
6
+ attr_reader route: Array[untyped]
7
+
8
+ attr_reader version: untyped
9
+
10
+ attr_reader record: untyped
11
+
12
+ attr_reader replacement: RecordSnapshot?
13
+
14
+ # : (route: Array[untyped], version: untyped, record: untyped, replacement: RecordSnapshot?) -> void
15
+ def initialize: (route: Array[untyped], version: untyped, record: untyped, replacement: RecordSnapshot?) -> void
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ # Generated from lib/paper_trail_diff/activity_collection_route_updater.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Replaces a collection event record along one explicit immutable snapshot route.
5
+ class ActivityCollectionRouteUpdater
6
+ # : (pool: SnapshotPool, relationship: ActivityRelationship) -> void
7
+ def initialize: (pool: SnapshotPool, relationship: ActivityRelationship) -> void
8
+
9
+ # : (RecordSnapshot, ActivityCollectionRouteChange, ?depth: Integer) -> [RecordSnapshot, bool]
10
+ def call: (RecordSnapshot, ActivityCollectionRouteChange, ?depth: Integer) -> [ RecordSnapshot, bool ]
11
+
12
+ private
13
+
14
+ @pool: SnapshotPool
15
+
16
+ @record_updater: ActivityCollectionRecordUpdater
17
+
18
+ @relationship: ActivityRelationship
19
+
20
+ # : (AssociationSnapshot, RecordSnapshot, ActivityCollectionRouteChange, Integer) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool]
21
+ def updated_records: (AssociationSnapshot, RecordSnapshot, ActivityCollectionRouteChange, Integer) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool ]
22
+
23
+ # : (AssociationSnapshot, RecordSnapshot, ActivityCollectionRouteChange) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool]
24
+ def leaf_records: (AssociationSnapshot, RecordSnapshot, ActivityCollectionRouteChange) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool ]
25
+
26
+ # : (AssociationSnapshot, ActivityCollectionRouteChange, Integer) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]?
27
+ def targeted_parent: (AssociationSnapshot, ActivityCollectionRouteChange, Integer) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]?
28
+
29
+ # : (AssociationSnapshot, ActivityCollectionRouteChange, Integer) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool]
30
+ def recursive_records: (AssociationSnapshot, ActivityCollectionRouteChange, Integer) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool, bool ]
31
+
32
+ # : ([RecordSnapshot?, RecordSnapshot?, bool], RecordSnapshot, RecordSnapshot, bool) -> [RecordSnapshot?, RecordSnapshot?, bool]
33
+ def recursive_transition: ([ RecordSnapshot?, RecordSnapshot?, bool ], RecordSnapshot, RecordSnapshot, bool) -> [ RecordSnapshot?, RecordSnapshot?, bool ]
34
+
35
+ # : (Array[RecordSnapshot], Integer, RecordSnapshot, RecordSnapshot, bool) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]
36
+ def targeted_parent_replacement: (Array[RecordSnapshot], Integer, RecordSnapshot, RecordSnapshot, bool) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]
37
+
38
+ # : (AssociationSnapshot, untyped, ActivityCollectionRouteChange) -> Integer?
39
+ def nested_owner_position: (AssociationSnapshot, untyped, ActivityCollectionRouteChange) -> Integer?
40
+
41
+ # : (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
42
+ def replace_association: (RecordSnapshot, String, AssociationSnapshot) -> RecordSnapshot
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ # Generated from lib/paper_trail_diff/activity_event_record_normalizer.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Normalizes one event record with the historical reader for its boundary.
5
+ class ActivityEventRecordNormalizer
6
+ # : (?association_reader: untyped) -> void
7
+ def initialize: (?association_reader: untyped) -> void
8
+
9
+ # : (untyped, reflection: untyped, subtree: AssociationTree, path: String, normalizer: SnapshotNormalizer, root_endpoint: untyped, context_endpoint: untyped) -> RecordSnapshot?
10
+ def call: (untyped, reflection: untyped, subtree: AssociationTree, path: String, normalizer: SnapshotNormalizer, root_endpoint: untyped, context_endpoint: untyped) -> RecordSnapshot?
11
+
12
+ private
13
+
14
+ @association_reader: untyped
15
+
16
+ # : (untyped, habtm_version: untyped) -> HistoricalAssociationReifier
17
+ def historical_reader: (untyped, habtm_version: untyped) -> HistoricalAssociationReifier
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ # Generated from lib/paper_trail_diff/activity_event_record_resolver.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Reconstructs an event's post-change record or immutable scalar delta.
5
+ class ActivityEventRecordResolver
6
+ RECORD_AFTER_HANDLERS: untyped
7
+
8
+ # : (?record_transition: untyped) -> void
9
+ def initialize: (?record_transition: untyped) -> void
10
+
11
+ # : (untyped) -> untyped
12
+ def record_after: (untyped) -> untyped
13
+
14
+ # : (untyped) -> ActivitySnapshotDelta?
15
+ def snapshot_delta: (untyped) -> ActivitySnapshotDelta?
16
+
17
+ # : (untyped) -> untyped
18
+ def changed_record_after: (untyped) -> untyped
19
+
20
+ # : (untyped) -> untyped
21
+ def created_record_after: (untyped) -> untyped
22
+
23
+ # : (untyped) -> untyped
24
+ def updated_record_after: (untyped) -> untyped
25
+
26
+ # Mirrors PaperTrail's changeset deserialization without resolving
27
+ # +version.item+, which would issue one live-record query per event.
28
+ # : (untyped, untyped) -> untyped
29
+ def deserialized_changeset: (untyped, untyped) -> untyped
30
+
31
+ private
32
+
33
+ @record_transition: untyped
34
+
35
+ # : (untyped, untyped) -> Hash[untyped, untyped]
36
+ def after_attributes: (untyped, untyped) -> Hash[untyped, untyped]
37
+
38
+ # : (untyped, untyped) -> untyped
39
+ def apply_changes: (untyped, untyped) -> untyped
40
+
41
+ # : (untyped, untyped, untyped) -> untyped
42
+ def standard_changeset: (untyped, untyped, untyped) -> untyped
43
+ end
44
+ end
@@ -0,0 +1,47 @@
1
+ # Generated from lib/paper_trail_diff/activity_event_route_finder.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Finds explicitly selected collection and belongs-to routes for one event type.
5
+ class ActivityEventRouteFinder
6
+ # : (AssociationTraversal) -> void
7
+ def initialize: (AssociationTraversal) -> void
8
+
9
+ # : (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
10
+ def collection_routes: (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
11
+
12
+ # : (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
13
+ def belongs_to_routes: (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
14
+
15
+ private
16
+
17
+ @belongs_to_routes: Hash[Array[untyped], Array[Array[untyped]]]
18
+
19
+ @collection_routes: Hash[Array[untyped], Array[Array[untyped]]]
20
+
21
+ @traversal: AssociationTraversal
22
+
23
+ # Timelines interleave event types, so every requested combination is
24
+ # retained. Model, tree, and path are fixed per adapter, leaving one entry
25
+ # per selected item type.
26
+ # : (Hash[Array[untyped], Array[Array[untyped]]], untyped, AssociationTree, String, String, Symbol) -> Array[Array[untyped]]
27
+ def cached: (Hash[Array[untyped], Array[Array[untyped]]], untyped, AssociationTree, String, String, Symbol) -> Array[Array[untyped]]
28
+
29
+ # : (Array[untyped]) -> Array[untyped]
30
+ def cache_key: (Array[untyped]) -> Array[untyped]
31
+
32
+ # : (Array[Array[untyped]]) -> Array[Array[untyped]]
33
+ def freeze_routes: (Array[Array[untyped]]) -> Array[Array[untyped]]
34
+
35
+ # : (untyped, AssociationTree, String, Symbol, path: String) -> Array[Array[untyped]]
36
+ def routes: (untyped, AssociationTree, String, Symbol, path: String) -> Array[Array[untyped]]
37
+
38
+ # : (untyped, AssociationTree, String, Symbol, String) -> Array[Array[untyped]]
39
+ def routes_for_reflection: (untyped, AssociationTree, String, Symbol, String) -> Array[Array[untyped]]
40
+
41
+ # : (untyped, String, Symbol) -> bool
42
+ def direct_route?: (untyped, String, Symbol) -> bool
43
+
44
+ # : (untyped, Symbol) -> bool
45
+ def supported_direct_reflection?: (untyped, Symbol) -> bool
46
+ end
47
+ end
@@ -1,138 +1,46 @@
1
1
  # Generated from lib/paper_trail_diff/activity_event_snapshot_refresher.rb with RBS::Inline
2
2
 
3
3
  module PaperTrailDiff
4
- # Applies safe descendant event deltas without rebuilding an entire selected branch.
5
- # rubocop:disable Metrics/ClassLength
4
+ # Dispatches safe descendant events to focused immutable snapshot appliers.
6
5
  class ActivityEventSnapshotRefresher
7
- RECORD_AFTER_HANDLERS: untyped
8
-
9
6
  # : (traversal: AssociationTraversal, pool: SnapshotPool, components: untyped, ?association_reader: untyped, ?record_transition: untyped) -> void
10
7
  def initialize: (traversal: AssociationTraversal, pool: SnapshotPool, components: untyped, ?association_reader: untyped, ?record_transition: untyped) -> void
11
8
 
12
- # : (untyped, untyped, RecordSnapshot, Array[String], ActivityEvent?) -> [bool, RecordSnapshot?]
13
- def call: (untyped, untyped, RecordSnapshot, Array[String], ActivityEvent?) -> [ bool, RecordSnapshot? ]
14
-
15
- private
16
-
17
- @association_reader: untyped
18
-
19
- @components: untyped
20
-
21
- @pool: SnapshotPool
22
-
23
- @record_transition: untyped
24
-
25
- @traversal: AssociationTraversal
9
+ # : (SnapshotPool, untyped) -> void
10
+ def configure_appliers: (SnapshotPool, untyped) -> void
26
11
 
27
- # : (Array[Array[untyped]], untyped) -> bool
28
- def unsafe_through_membership_event?: (Array[Array[untyped]], untyped) -> bool
12
+ # : (SnapshotPool) -> ActivityCollectionRouteUpdater
13
+ def collection_updater: (SnapshotPool) -> ActivityCollectionRouteUpdater
29
14
 
30
- # : (Array[Array[untyped]], ActivitySnapshotDelta?) -> bool
31
- def unsafe_nested_membership_delta?: (Array[Array[untyped]], ActivitySnapshotDelta?) -> bool
15
+ # : (ActivityEventRecordNormalizer, ActivityCollectionRouteUpdater) -> ActivityCollectionEventApplier
16
+ def collection_applier: (ActivityEventRecordNormalizer, ActivityCollectionRouteUpdater) -> ActivityCollectionEventApplier
32
17
 
33
- # : (untyped, untyped, RecordSnapshot, SnapshotNormalizer, Array[Array[untyped]], untyped, ActivitySnapshotDelta?) -> [bool, RecordSnapshot]
34
- def collection_target_snapshot: (untyped, untyped, RecordSnapshot, SnapshotNormalizer, Array[Array[untyped]], untyped, ActivitySnapshotDelta?) -> [ bool, RecordSnapshot ]
18
+ # : (ActivityEventRecordNormalizer) -> ActivityBelongsToEventApplier
19
+ def belongs_to_applier: (ActivityEventRecordNormalizer) -> ActivityBelongsToEventApplier
35
20
 
36
- # : (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, untyped, untyped) -> [untyped, RecordSnapshot?]
37
- def collection_route_event_state: (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?, Array[untyped], SnapshotNormalizer, untyped, untyped) -> [ untyped, RecordSnapshot? ]
38
-
39
- # : (untyped, Array[untyped], SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
40
- def normalized_collection_event_record: (untyped, Array[untyped], SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
41
-
42
- # : (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?) -> RecordSnapshot?
43
- def existing_delta_record: (RecordSnapshot, Array[untyped], untyped, ActivitySnapshotDelta?) -> RecordSnapshot?
44
-
45
- # : (RecordSnapshot, Array[untyped], ActivitySnapshotDelta) -> RecordSnapshot?
46
- def nested_delta_owner: (RecordSnapshot, Array[untyped], ActivitySnapshotDelta) -> RecordSnapshot?
47
-
48
- # : (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
49
- def direct_collection_routes: (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
50
-
51
- # : (RecordSnapshot, Array[untyped], untyped, untyped, RecordSnapshot?, ?depth: Integer) -> [RecordSnapshot, bool]
52
- def replace_collection_route: (RecordSnapshot, Array[untyped], untyped, untyped, RecordSnapshot?, ?depth: Integer) -> [ RecordSnapshot, bool ]
53
-
54
- # : (AssociationSnapshot, untyped, untyped, untyped, RecordSnapshot, RecordSnapshot?) -> RecordSnapshot?
55
- def collection_event_child: (AssociationSnapshot, untyped, untyped, untyped, RecordSnapshot, RecordSnapshot?) -> RecordSnapshot?
56
-
57
- # : (AssociationSnapshot, Array[untyped], untyped, untyped, RecordSnapshot?, Integer) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]?
58
- def replace_targeted_collection_parent: (AssociationSnapshot, Array[untyped], untyped, untyped, RecordSnapshot?, Integer) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]?
21
+ # : (untyped, untyped, RecordSnapshot, Array[String], ActivityEvent?) -> [bool, RecordSnapshot?]
22
+ def call: (untyped, untyped, RecordSnapshot, Array[String], ActivityEvent?) -> [ bool, RecordSnapshot? ]
59
23
 
60
- # : (Array[RecordSnapshot], Integer, RecordSnapshot, RecordSnapshot, bool) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]
61
- def targeted_parent_replacement: (Array[RecordSnapshot], Integer, RecordSnapshot, RecordSnapshot, bool) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]
24
+ private
62
25
 
63
- # : (AssociationSnapshot, untyped, untyped, untyped) -> Integer?
64
- def nested_owner_position: (AssociationSnapshot, untyped, untyped, untyped) -> Integer?
26
+ @belongs_to_applier: ActivityBelongsToEventApplier
65
27
 
66
- # : (untyped, untyped, RecordSnapshot, AssociationTree, SnapshotNormalizer, untyped) -> [bool, RecordSnapshot?]
67
- def belongs_to_target_snapshot: (untyped, untyped, RecordSnapshot, AssociationTree, SnapshotNormalizer, untyped) -> [ bool, RecordSnapshot? ]
28
+ @collection_applier: ActivityCollectionEventApplier
68
29
 
69
- # : (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
70
- def belongs_to_routes: (untyped, AssociationTree, String, ?path: String) -> Array[Array[untyped]]
30
+ @components: untyped
71
31
 
72
- # : (Array[untyped], untyped, SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
73
- def normalized_route_record: (Array[untyped], untyped, SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
32
+ @record_resolver: ActivityEventRecordResolver
74
33
 
75
- # : (RecordSnapshot, Array[untyped], untyped, RecordSnapshot?, ?depth: Integer) -> [RecordSnapshot, bool]
76
- def replace_route: (RecordSnapshot, Array[untyped], untyped, RecordSnapshot?, ?depth: Integer) -> [ RecordSnapshot, bool ]
34
+ @relationship: ActivityRelationship
77
35
 
78
- # : (Array[RecordSnapshot], untyped, RecordSnapshot?) -> Array[RecordSnapshot]
79
- def replace_existing_target: (Array[RecordSnapshot], untyped, RecordSnapshot?) -> Array[RecordSnapshot]
36
+ @route_finder: ActivityEventRouteFinder
80
37
 
81
38
  # : (untyped) -> untyped
82
39
  def record_after: (untyped) -> untyped
83
40
 
84
- # PaperTrail create/update versions contain deserialized change pairs, so
85
- # their post-event records need no successor query.
86
- # : (untyped) -> untyped
87
- def changed_record_after: (untyped) -> untyped
88
-
89
- # : (untyped) -> untyped
90
- def created_record_after: (untyped) -> untyped
91
-
92
- # : (untyped) -> untyped
93
- def updated_record_after: (untyped) -> untyped
94
-
95
- # : (untyped, untyped) -> Hash[untyped, untyped]
96
- def after_attributes: (untyped, untyped) -> Hash[untyped, untyped]
97
-
98
- # : (untyped, untyped) -> untyped
99
- def apply_changes: (untyped, untyped) -> untyped
100
-
101
- # Mirrors PaperTrail's changeset deserialization without resolving
102
- # +version.item+, which would issue one live-record query per event.
103
41
  # : (untyped, untyped) -> untyped
104
42
  def deserialized_changeset: (untyped, untyped) -> untyped
105
43
 
106
- # : (untyped, untyped, untyped) -> untyped
107
- def standard_changeset: (untyped, untyped, untyped) -> untyped
108
-
109
- # : (untyped) -> ActivitySnapshotDelta?
110
- def activity_snapshot_delta: (untyped) -> ActivitySnapshotDelta?
111
-
112
- # : (untyped, untyped, RecordSnapshot, ?state: Symbol) -> bool
113
- def member_of_owner?: (untyped, untyped, RecordSnapshot, ?state: Symbol) -> bool
114
-
115
- # : (untyped, untyped, state: Symbol) -> untyped
116
- def event_attribute: (untyped, untyped, state: Symbol) -> untyped
117
-
118
- # : (untyped, untyped, state: Symbol) -> untyped
119
- def relationship_owner_id: (untyped, untyped, state: Symbol) -> untyped
120
-
121
- # : (untyped, untyped, AssociationTree, String, SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
122
- def normalize_event_record: (untyped, untyped, AssociationTree, String, SnapshotNormalizer, untyped, untyped) -> RecordSnapshot?
123
-
124
- # : (untyped, habtm_version: untyped) -> HistoricalAssociationReifier
125
- def historical_reader: (untyped, habtm_version: untyped) -> HistoricalAssociationReifier
126
-
127
- # : (AssociationSnapshot, untyped, RecordSnapshot?) -> [Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool]
128
- def replace_collection_record: (AssociationSnapshot, untyped, RecordSnapshot?) -> [ Array[RecordSnapshot], RecordSnapshot?, RecordSnapshot?, bool ]
129
-
130
- # : (Array[RecordSnapshot], Integer?, RecordSnapshot?) -> Array[RecordSnapshot]
131
- def replacement_collection_records: (Array[RecordSnapshot], Integer?, RecordSnapshot?) -> Array[RecordSnapshot]
132
-
133
- # : (untyped, RecordSnapshot?) -> String
134
- def replacement_type: (untyped, RecordSnapshot?) -> String
135
-
136
44
  # : (untyped) -> untyped
137
45
  def endpoint_model_class: (untyped) -> untyped
138
46
  end
@@ -0,0 +1,23 @@
1
+ # Generated from lib/paper_trail_diff/activity_relationship.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Reads event-side foreign keys and matches them to an immutable snapshot owner.
5
+ class ActivityRelationship
6
+ # : (untyped, untyped, RecordSnapshot, ?state: Symbol) -> bool
7
+ def member_of_owner?: (untyped, untyped, RecordSnapshot, ?state: Symbol) -> bool
8
+
9
+ # : (untyped, untyped, state: Symbol) -> untyped
10
+ def owner_id: (untyped, untyped, state: Symbol) -> untyped
11
+
12
+ private
13
+
14
+ # : (untyped, untyped, state: Symbol) -> Array[String]
15
+ def relationship_owner_values: (untyped, untyped, state: Symbol) -> Array[String]
16
+
17
+ # : (untyped, untyped, state: Symbol) -> untyped
18
+ def event_attribute: (untyped, untyped, state: Symbol) -> untyped
19
+
20
+ # : (untyped, RecordSnapshot) -> Array[String]
21
+ def owner_types: (untyped, RecordSnapshot) -> Array[String]
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ # Generated from lib/paper_trail_diff/activity_root_steps.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Root checkpoint steps recovered from the snapshots an activity pass retained,
5
+ # so a combined result does not reconstruct the same boundaries twice.
6
+ module ActivityRootSteps
7
+ # : (Array[untyped], Hash[Array[untyped], RecordSnapshot?]) -> Array[Step]
8
+ def self?.call: (Array[untyped], Hash[Array[untyped], RecordSnapshot?]) -> Array[Step]
9
+
10
+ # : (untyped) -> Array[untyped]
11
+ def self?.version_key: (untyped) -> Array[untyped]
12
+ end
13
+ end
@@ -6,8 +6,8 @@ module PaperTrailDiff
6
6
  # : (snapshotter: untyped, refresher: untyped, preparer: untyped) -> void
7
7
  def initialize: (snapshotter: untyped, refresher: untyped, preparer: untyped) -> void
8
8
 
9
- # : (untyped, Array[untyped], ?start_at: untyped) -> void
10
- def prepare: (untyped, Array[untyped], ?start_at: untyped) -> void
9
+ # : (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
10
+ def prepare: (untyped, Array[untyped], ?start_at: untyped, ?end_at: untyped) -> void
11
11
 
12
12
  # : (untyped, untyped) -> RecordSnapshot?
13
13
  def call: (untyped, untyped) -> RecordSnapshot?
@@ -27,6 +27,9 @@ module PaperTrailDiff
27
27
 
28
28
  @tree: AssociationTree
29
29
 
30
+ # : () -> Array[ActivityStep]
31
+ def no_steps: () -> Array[ActivityStep]
32
+
30
33
  # : () -> Array[ActivityStep]
31
34
  def build_between_versions: () -> Array[ActivityStep]
32
35
 
@@ -42,23 +45,30 @@ module PaperTrailDiff
42
45
  # : (Array[untyped], ?range_start: untyped, ?range_end: untyped) -> Array[ActivityEvent]
43
46
  def collect_events: (Array[untyped], ?range_start: untyped, ?range_end: untyped) -> Array[ActivityEvent]
44
47
 
45
- # : (Array[untyped], ?start_at: untyped) -> void
46
- def prepare_history: (Array[untyped], ?start_at: untyped) -> void
48
+ # : (Array[untyped], ?end_at: untyped) -> void
49
+ def prepare_history: (Array[untyped], ?end_at: untyped) -> void
47
50
 
48
51
  # : (Array[untyped], Array[ActivityEvent], ?current: untyped, ?final_boundary: ActivityBoundary?, ?final_snapshot: RecordSnapshot?) -> Array[ActivityStep]
49
52
  def build_event_steps: (Array[untyped], Array[ActivityEvent], ?current: untyped, ?final_boundary: ActivityBoundary?, ?final_snapshot: RecordSnapshot?) -> Array[ActivityStep]
50
53
 
51
- # : (Array[untyped], Array[ActivityEvent], ?current: untyped) -> ActivityHistory
52
- def event_history: (Array[untyped], Array[ActivityEvent], ?current: untyped) -> ActivityHistory
54
+ # Appends the transition into an explicit closing boundary, which is either
55
+ # a requested current record or the absence a final root destroy leaves.
56
+ # : (ActivityHistory, Array[ActivityEvent], ActivityBoundary?, RecordSnapshot?) -> Array[ActivityStep]
57
+ def activity_steps: (ActivityHistory, Array[ActivityEvent], ActivityBoundary?, RecordSnapshot?) -> Array[ActivityStep]
53
58
 
54
- # : (Array[untyped], ActivityHistory) -> Analysis
55
- def build_analysis: (Array[untyped], ActivityHistory) -> Analysis
59
+ # A destroyed root has no later version, but its own event states that
60
+ # nothing follows it, so the removal can still close the timeline.
61
+ # : (Array[untyped]) -> ActivityBoundary?
62
+ def destroyed_boundary: (Array[untyped]) -> ActivityBoundary?
56
63
 
57
- # : (Array[untyped], Array[RecordSnapshot?]) -> Array[Step]
58
- def build_root_steps: (Array[untyped], Array[RecordSnapshot?]) -> Array[Step]
64
+ # : (Array[untyped], Array[ActivityEvent], ?current: untyped) -> ActivityHistory
65
+ def event_history: (Array[untyped], Array[ActivityEvent], ?current: untyped) -> ActivityHistory
59
66
 
60
- # : (untyped) -> Array[untyped]
61
- def version_key: (untyped) -> Array[untyped]
67
+ # Only the activity view gains the closing removal. The endpoint diff and
68
+ # the root timeline keep their `compare` and `timeline` semantics, under
69
+ # which the state at a destroy version is the state before the deletion.
70
+ # : (Array[untyped], Array[ActivityEvent], ActivityHistory) -> Analysis
71
+ def build_analysis: (Array[untyped], Array[ActivityEvent], ActivityHistory) -> Analysis
62
72
 
63
73
  # : () -> TimeActivityTimelineBuilder
64
74
  def time_builder: () -> TimeActivityTimelineBuilder
@@ -9,6 +9,11 @@ module PaperTrailDiff
9
9
 
10
10
  attr_reader activity_timeline: Array[ActivityStep]?
11
11
 
12
+ # The result for a record whose requested history contains no versions,
13
+ # which is an empty history rather than a failed request.
14
+ # : () -> Analysis
15
+ def self.empty: () -> Analysis
16
+
12
17
  # : (diff: Diff, timeline: Array[Step], ?activity_timeline: Array[ActivityStep]?) -> void
13
18
  def initialize: (diff: Diff, timeline: Array[Step], ?activity_timeline: Array[ActivityStep]?) -> void
14
19
 
@@ -50,9 +50,16 @@ module PaperTrailDiff
50
50
  # : (Array[identity]) -> Array[identity]
51
51
  def sorted_identities: (Array[identity]) -> Array[identity]
52
52
 
53
+ # Identities sort by type first so that mixed id types stay comparable, then
54
+ # naturally within one type. Ordering by the printed form instead would put
55
+ # id 10 before id 2, which is deterministic but reads as unsorted wherever a
56
+ # result is rendered.
53
57
  # : (identity) -> Array[untyped]
54
58
  def sortable_identity: (identity) -> Array[untyped]
55
59
 
60
+ # : (untyped) -> Array[untyped]
61
+ def sortable_id: (untyped) -> Array[untyped]
62
+
56
63
  # : (identity) -> void
57
64
  def raise_duplicate_identity!: (identity) -> void
58
65
  end
@@ -7,12 +7,15 @@ module PaperTrailDiff
7
7
 
8
8
  attr_reader after: RecordSnapshot?
9
9
 
10
+ # The origin is recorded by serial rather than by reference, because
11
+ # holding it would retain every earlier snapshot at the same path for the
12
+ # whole timeline.
10
13
  # : (from: AssociationSnapshot, before: RecordSnapshot?, after: RecordSnapshot?) -> void
11
14
  def initialize: (from: AssociationSnapshot, before: RecordSnapshot?, after: RecordSnapshot?) -> void
12
15
 
13
16
  # : (AssociationSnapshot) -> bool
14
17
  def from?: (AssociationSnapshot) -> bool
15
18
 
16
- @from_object_id: Integer
19
+ @from_serial: Integer
17
20
  end
18
21
  end
@@ -6,6 +6,18 @@ module PaperTrailDiff
6
6
  # : (untyped, untyped) -> void
7
7
  def self?.validate_pair!: (untyped, untyped) -> void
8
8
 
9
+ # Two versions carry no visible cue about which is earlier, so transposing
10
+ # them is easy to do by accident and impossible to detect afterwards: the
11
+ # result is a valid inverse diff and carries no direction of its own. It is
12
+ # also redundant, because the two orders differ only in which side of each
13
+ # change is `from`. A current-record endpoint is exempt: it is self-evidently
14
+ # the live state, so putting it first is a deliberate reverse comparison.
15
+ # : (untyped, untyped) -> void
16
+ def self?.validate_order!: (untyped, untyped) -> void
17
+
18
+ # : (untyped, untyped) -> bool
19
+ def self?.reversed_versions?: (untyped, untyped) -> bool
20
+
9
21
  # : (untyped) -> void
10
22
  def self?.validate!: (untyped) -> void
11
23