paper_trail_diff 0.3.1 → 0.5.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. data/README.md +316 -32
  4. data/lib/paper_trail_diff/activity_boundary.rb +21 -0
  5. data/lib/paper_trail_diff/activity_event_route_finder.rb +24 -44
  6. data/lib/paper_trail_diff/activity_root_steps.rb +27 -0
  7. data/lib/paper_trail_diff/activity_snapshot_sequence.rb +8 -3
  8. data/lib/paper_trail_diff/activity_timeline_builder.rb +47 -32
  9. data/lib/paper_trail_diff/analysis.rb +9 -0
  10. data/lib/paper_trail_diff/analysis_batch.rb +74 -0
  11. data/lib/paper_trail_diff/batch_boundary_resolver.rb +137 -0
  12. data/lib/paper_trail_diff/batched_root_analyzer.rb +50 -0
  13. data/lib/paper_trail_diff/batched_root_versions.rb +131 -0
  14. data/lib/paper_trail_diff/collection_comparator.rb +14 -1
  15. data/lib/paper_trail_diff/collection_transition.rb +6 -3
  16. data/lib/paper_trail_diff/comparison_batch.rb +37 -13
  17. data/lib/paper_trail_diff/endpoint.rb +27 -2
  18. data/lib/paper_trail_diff/errors.rb +3 -0
  19. data/lib/paper_trail_diff/historical_association_reifier.rb +8 -5
  20. data/lib/paper_trail_diff/historical_snapshot_store.rb +12 -9
  21. data/lib/paper_trail_diff/paper_trail_adapter.rb +49 -33
  22. data/lib/paper_trail_diff/prepared_association_reifier.rb +8 -5
  23. data/lib/paper_trail_diff/prepared_edge_loader.rb +6 -4
  24. data/lib/paper_trail_diff/prepared_history_loader.rb +3 -2
  25. data/lib/paper_trail_diff/prepared_record_index.rb +90 -15
  26. data/lib/paper_trail_diff/snapshot.rb +26 -0
  27. data/lib/paper_trail_diff/snapshot_normalizer.rb +14 -2
  28. data/lib/paper_trail_diff/time_activity_timeline_builder.rb +52 -32
  29. data/lib/paper_trail_diff/time_version_range.rb +11 -0
  30. data/lib/paper_trail_diff/timeline_builder.rb +3 -3
  31. data/lib/paper_trail_diff/timeline_range.rb +66 -6
  32. data/lib/paper_trail_diff/traversal_preparer.rb +40 -0
  33. data/lib/paper_trail_diff/version.rb +1 -1
  34. data/lib/paper_trail_diff/version_association_candidate_scope.rb +46 -19
  35. data/lib/paper_trail_diff.rb +37 -5
  36. data/sig/generated/paper_trail_diff/activity_boundary.rbs +9 -0
  37. data/sig/generated/paper_trail_diff/activity_event_route_finder.rbs +10 -17
  38. data/sig/generated/paper_trail_diff/activity_root_steps.rbs +13 -0
  39. data/sig/generated/paper_trail_diff/activity_snapshot_sequence.rbs +2 -2
  40. data/sig/generated/paper_trail_diff/activity_timeline_builder.rbs +20 -10
  41. data/sig/generated/paper_trail_diff/analysis.rbs +5 -0
  42. data/sig/generated/paper_trail_diff/analysis_batch.rbs +42 -0
  43. data/sig/generated/paper_trail_diff/batch_boundary_resolver.rbs +62 -0
  44. data/sig/generated/paper_trail_diff/batched_root_analyzer.rbs +28 -0
  45. data/sig/generated/paper_trail_diff/batched_root_versions.rbs +62 -0
  46. data/sig/generated/paper_trail_diff/collection_comparator.rbs +7 -0
  47. data/sig/generated/paper_trail_diff/collection_transition.rbs +4 -1
  48. data/sig/generated/paper_trail_diff/comparison_batch.rbs +15 -0
  49. data/sig/generated/paper_trail_diff/endpoint.rbs +12 -0
  50. data/sig/generated/paper_trail_diff/errors.rbs +4 -0
  51. data/sig/generated/paper_trail_diff/historical_association_reifier.rbs +1 -1
  52. data/sig/generated/paper_trail_diff/historical_snapshot_store.rbs +2 -3
  53. data/sig/generated/paper_trail_diff/paper_trail_adapter.rbs +16 -7
  54. data/sig/generated/paper_trail_diff/prepared_association_reifier.rbs +1 -1
  55. data/sig/generated/paper_trail_diff/prepared_edge_loader.rbs +1 -0
  56. data/sig/generated/paper_trail_diff/prepared_history_loader.rbs +2 -2
  57. data/sig/generated/paper_trail_diff/prepared_record_index.rbs +39 -6
  58. data/sig/generated/paper_trail_diff/snapshot.rbs +20 -0
  59. data/sig/generated/paper_trail_diff/snapshot_normalizer.rbs +8 -0
  60. data/sig/generated/paper_trail_diff/time_activity_timeline_builder.rbs +21 -10
  61. data/sig/generated/paper_trail_diff/time_version_range.rbs +7 -0
  62. data/sig/generated/paper_trail_diff/timeline_builder.rbs +2 -2
  63. data/sig/generated/paper_trail_diff/timeline_range.rbs +35 -2
  64. data/sig/generated/paper_trail_diff/traversal_preparer.rbs +22 -0
  65. data/sig/generated/paper_trail_diff/version_association_candidate_scope.rbs +17 -4
  66. data/sig/generated/paper_trail_diff.rbs +13 -3
  67. metadata +16 -4
@@ -22,8 +22,25 @@ module PaperTrailDiff
22
22
 
23
23
  @tree: AssociationTree
24
24
 
25
- # : () -> [ActivityHistory, Array[untyped]]
26
- def history_and_versions: () -> [ ActivityHistory, Array[untyped] ]
25
+ # : () -> [ActivityHistory, Array[untyped], ActivityStep?]
26
+ def history_and_versions: () -> [ ActivityHistory, Array[untyped], ActivityStep? ]
27
+
28
+ # : (Array[untyped], Array[ActivityEvent]) -> ActivityHistory
29
+ def build_history: (Array[untyped], Array[ActivityEvent]) -> ActivityHistory
30
+
31
+ # : (ActivityHistory, ActivityStep?) -> Array[ActivityStep]
32
+ def activity_steps: (ActivityHistory, ActivityStep?) -> Array[ActivityStep]
33
+
34
+ # : (Array[ActivityEvent]) -> Array[ActivityEvent]
35
+ def selected_events: (Array[ActivityEvent]) -> Array[ActivityEvent]
36
+
37
+ # The window's last selected mutation is the root's own destruction, so the
38
+ # timeline closes on the absence it leaves rather than on a later boundary.
39
+ # : (ActivityHistory, ActivityEvent?) -> ActivityStep?
40
+ def closing_step: (ActivityHistory, ActivityEvent?) -> ActivityStep?
41
+
42
+ # : (ActivityEvent?) -> bool
43
+ def terminal_destroy?: (ActivityEvent?) -> bool
27
44
 
28
45
  # : (Array[untyped]) -> void
29
46
  def prepare_history: (Array[untyped]) -> void
@@ -31,16 +48,10 @@ module PaperTrailDiff
31
48
  # : (Array[untyped]) -> Array[ActivityEvent]
32
49
  def collect_events: (Array[untyped]) -> Array[ActivityEvent]
33
50
 
34
- # : (Array[ActivityEvent]) -> bool
35
- def time_events?: (Array[ActivityEvent]) -> bool
51
+ # : (Array[ActivityEvent], Array[ActivityEvent]) -> bool
52
+ def time_events?: (Array[ActivityEvent], Array[ActivityEvent]) -> bool
36
53
 
37
54
  # : (ActivityEvent, Array[ActivityEvent]) -> bool
38
55
  def later_event?: (ActivityEvent, Array[ActivityEvent]) -> bool
39
-
40
- # : (Array[untyped], Hash[Array[untyped], RecordSnapshot?]) -> Array[Step]
41
- def root_steps: (Array[untyped], Hash[Array[untyped], RecordSnapshot?]) -> Array[Step]
42
-
43
- # : (untyped) -> Array[untyped]
44
- def version_key: (untyped) -> Array[untyped]
45
56
  end
46
57
  end
@@ -18,6 +18,13 @@ module PaperTrailDiff
18
18
  # : () -> untyped
19
19
  def versions_relation: () -> untyped
20
20
 
21
+ # A window closing on the record's own destruction needs no later version:
22
+ # the destroy reveals the preceding mutation and nothing can follow it, so
23
+ # demanding a checkpoint that can never be written would reject the range
24
+ # permanently.
25
+ # : (Array[untyped]) -> bool
26
+ def terminal_destroy?: (Array[untyped]) -> bool
27
+
21
28
  # : (untyped) -> untyped
22
29
  def trailing_version: (untyped) -> untyped
23
30
 
@@ -3,8 +3,8 @@
3
3
  module PaperTrailDiff
4
4
  # Selects and compares a chronological slice of a record's version history.
5
5
  class TimelineBuilder
6
- # : (untyped, from: untyped, to: untyped, snapshotter: untyped, ?within: untyped) -> void
7
- def initialize: (untyped, from: untyped, to: untyped, snapshotter: untyped, ?within: untyped) -> void
6
+ # : (untyped, from: untyped, to: untyped, snapshotter: untyped, ?within: untyped, ?versions: Array[untyped]?) -> void
7
+ def initialize: (untyped, from: untyped, to: untyped, snapshotter: untyped, ?within: untyped, ?versions: Array[untyped]?) -> void
8
8
 
9
9
  # : () -> Array[Step]
10
10
  def build: () -> Array[Step]
@@ -3,15 +3,24 @@
3
3
  module PaperTrailDiff
4
4
  # Chooses explicit-version or wall-clock selection for one timeline request.
5
5
  class TimelineRange
6
+ BOUNDARY_SYMBOLS: untyped
7
+
6
8
  attr_reader from: untyped
7
9
 
8
10
  attr_reader to: untyped
9
11
 
10
12
  attr_reader time_range: TimeRange?
11
13
 
12
- # : (untyped, from: untyped, to: untyped, within: untyped) -> void
13
- def initialize: (untyped, from: untyped, to: untyped, within: untyped) -> void
14
+ # : (untyped, from: untyped, to: untyped, within: untyped, ?versions: Array[untyped]?) -> void
15
+ def initialize: (untyped, from: untyped, to: untyped, within: untyped, ?versions: Array[untyped]?) -> void
16
+
17
+ # A record with no versions has no first or last boundary to resolve, which
18
+ # is an empty history rather than a bad request.
19
+ # : () -> bool
20
+ def unresolved?: () -> bool
14
21
 
22
+ # A batch may have selected these versions already, in which case reselecting
23
+ # them per record would undo the batching.
15
24
  # : (?context_required: bool) -> Array[untyped]
16
25
  def select: (?context_required: bool) -> Array[untyped]
17
26
 
@@ -30,8 +39,32 @@ module PaperTrailDiff
30
39
 
31
40
  @record: untyped
32
41
 
42
+ @requested_from: untyped
43
+
44
+ @requested_to: untyped
45
+
33
46
  @to: untyped
34
47
 
48
+ @versions: Array[untyped]?
49
+
50
+ # : () -> Array[untyped]
51
+ def empty_versions: () -> Array[untyped]
52
+
53
+ # : (untyped) -> bool
54
+ def symbolic?: (untyped) -> bool
55
+
56
+ # Resolving `:first` and `:last` here keeps callers from depending on the
57
+ # order PaperTrail happens to give its versions association, which a caller
58
+ # is also free to reorder.
59
+ # : (untyped) -> untyped
60
+ def resolve: (untyped) -> untyped
61
+
62
+ # : () -> untyped
63
+ def ordered_versions: () -> untyped
64
+
65
+ # : () -> untyped
66
+ def versions_relation: () -> untyped
67
+
35
68
  # : (untyped) -> TimeRange?
36
69
  def build_time_range: (untyped) -> TimeRange?
37
70
 
@@ -0,0 +1,22 @@
1
+ # Generated from lib/paper_trail_diff/traversal_preparer.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Checks that a model can be traversed before any reconstruction starts, and
5
+ # that association tracking is actually available when history is involved.
6
+ class TraversalPreparer
7
+ # : (tree: AssociationTree, traversal: AssociationTraversal) -> void
8
+ def initialize: (tree: AssociationTree, traversal: AssociationTraversal) -> void
9
+
10
+ # : (untyped, historical: bool) -> void
11
+ def call: (untyped, historical: bool) -> void
12
+
13
+ private
14
+
15
+ @traversal: AssociationTraversal
16
+
17
+ @tree: AssociationTree
18
+
19
+ # : () -> void
20
+ def ensure_association_tracking!: () -> void
21
+ end
22
+ end
@@ -17,14 +17,27 @@ module PaperTrailDiff
17
17
 
18
18
  @version_class: untyped
19
19
 
20
+ # Only quoting helpers are needed, so the connection is borrowed for the
21
+ # duration of building the condition rather than checked out permanently,
22
+ # which Active Record 7.2 and newer can deprecate. Active Record 7.1 has no
23
+ # `with_connection` and reaches the same connection through the accessor.
24
+ # : () { (untyped) -> String } -> String
25
+ def with_connection: () { (untyped) -> String } -> String
26
+
20
27
  # : () -> String
21
28
  def candidate_condition: () -> String
22
29
 
23
- # : (String, String) -> String
24
- def activity_condition: (String, String) -> String
30
+ # : (untyped) -> String
31
+ def condition_sql: (untyped) -> String
32
+
33
+ # : (untyped, String, String) -> Hash[Symbol, String]
34
+ def quoted_columns: (untyped, String, String) -> Hash[Symbol, String]
35
+
36
+ # : (Hash[Symbol, String], String, untyped) -> String
37
+ def activity_condition: (Hash[Symbol, String], String, untyped) -> String
25
38
 
26
- # : (String, String) -> String
27
- def column: (String, String) -> String
39
+ # : (untyped, String, String) -> String
40
+ def column: (untyped, String, String) -> String
28
41
 
29
42
  # : (String) -> String
30
43
  def compact_sql: (String) -> String
@@ -1,7 +1,9 @@
1
1
  # Generated from lib/paper_trail_diff.rb with RBS::Inline
2
2
 
3
- # Structured version comparison for PaperTrail.
3
+ # Structured version comparison for PaperTrail. Each method is a thin,
4
+ # documented entry point, so this reads as an API listing rather than logic.
4
5
  module PaperTrailDiff
6
+ # rubocop:disable Metrics/ModuleLength
5
7
  DEFAULT_IGNORED_ATTRIBUTES: untyped
6
8
 
7
9
  SUPPORTED_ASSOCIATION_MACROS: untyped
@@ -19,13 +21,21 @@ module PaperTrailDiff
19
21
  def self.timeline: (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option) -> Array[Step]
20
22
 
21
23
  # Compares adjacent root and selected-descendant activity boundaries.
22
- # : (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option) -> Array[ActivityStep]
23
- def self.activity_timeline: (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option) -> Array[ActivityStep]
24
+ # `reload_live_endpoints:` applies only when `to:` is a current record; the
25
+ # other range forms never read live state.
26
+ # : (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?reload_live_endpoints: bool) -> Array[ActivityStep]
27
+ def self.activity_timeline: (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?reload_live_endpoints: bool) -> Array[ActivityStep]
24
28
 
25
29
  # Builds an endpoint diff and root-checkpoint timeline while normalizing each version once.
26
30
  # : (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool) -> Analysis
27
31
  def self.analyze: (untyped, ?from: untyped, ?to: untyped, ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool) -> Analysis
28
32
 
33
+ # Analyzes many roots over one shared time window, preparing their selected
34
+ # history once for the batch instead of once per record. Roots with no
35
+ # versions in the window return an empty `Analysis`.
36
+ # : (Array[untyped], ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool) -> Hash[identity, Analysis]
37
+ def self.analyze_many: (Array[untyped], ?within: untyped, ?associations: Array[String | Symbol], ?ignore: ignore_option, ?activity: bool) -> Hash[identity, Analysis]
38
+
29
39
  # Returns the association macros this release can normalize.
30
40
  # : () -> Array[Symbol]
31
41
  def self.supported_association_macros: () -> Array[Symbol]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paper_trail_diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Williams
@@ -59,14 +59,19 @@ files:
59
59
  - lib/paper_trail_diff/activity_range.rb
60
60
  - lib/paper_trail_diff/activity_relationship.rb
61
61
  - lib/paper_trail_diff/activity_root_snapshot_refresher.rb
62
+ - lib/paper_trail_diff/activity_root_steps.rb
62
63
  - lib/paper_trail_diff/activity_snapshot_delta.rb
63
64
  - lib/paper_trail_diff/activity_snapshot_sequence.rb
64
65
  - lib/paper_trail_diff/activity_timeline_builder.rb
65
66
  - lib/paper_trail_diff/activity_version_collector.rb
66
67
  - lib/paper_trail_diff/analysis.rb
68
+ - lib/paper_trail_diff/analysis_batch.rb
67
69
  - lib/paper_trail_diff/association_diff_traversal.rb
68
70
  - lib/paper_trail_diff/association_discovery.rb
69
71
  - lib/paper_trail_diff/association_traversal.rb
72
+ - lib/paper_trail_diff/batch_boundary_resolver.rb
73
+ - lib/paper_trail_diff/batched_root_analyzer.rb
74
+ - lib/paper_trail_diff/batched_root_versions.rb
70
75
  - lib/paper_trail_diff/branch_snapshot_refresher.rb
71
76
  - lib/paper_trail_diff/collection_comparator.rb
72
77
  - lib/paper_trail_diff/collection_identity_index.rb
@@ -105,6 +110,7 @@ files:
105
110
  - lib/paper_trail_diff/traversal.rb
106
111
  - lib/paper_trail_diff/traversal_emitter.rb
107
112
  - lib/paper_trail_diff/traversal_entry.rb
113
+ - lib/paper_trail_diff/traversal_preparer.rb
108
114
  - lib/paper_trail_diff/value_objects.rb
109
115
  - lib/paper_trail_diff/version.rb
110
116
  - lib/paper_trail_diff/version_association_candidate_scope.rb
@@ -126,14 +132,19 @@ files:
126
132
  - sig/generated/paper_trail_diff/activity_range.rbs
127
133
  - sig/generated/paper_trail_diff/activity_relationship.rbs
128
134
  - sig/generated/paper_trail_diff/activity_root_snapshot_refresher.rbs
135
+ - sig/generated/paper_trail_diff/activity_root_steps.rbs
129
136
  - sig/generated/paper_trail_diff/activity_snapshot_delta.rbs
130
137
  - sig/generated/paper_trail_diff/activity_snapshot_sequence.rbs
131
138
  - sig/generated/paper_trail_diff/activity_timeline_builder.rbs
132
139
  - sig/generated/paper_trail_diff/activity_version_collector.rbs
133
140
  - sig/generated/paper_trail_diff/analysis.rbs
141
+ - sig/generated/paper_trail_diff/analysis_batch.rbs
134
142
  - sig/generated/paper_trail_diff/association_diff_traversal.rbs
135
143
  - sig/generated/paper_trail_diff/association_discovery.rbs
136
144
  - sig/generated/paper_trail_diff/association_traversal.rbs
145
+ - sig/generated/paper_trail_diff/batch_boundary_resolver.rbs
146
+ - sig/generated/paper_trail_diff/batched_root_analyzer.rbs
147
+ - sig/generated/paper_trail_diff/batched_root_versions.rbs
137
148
  - sig/generated/paper_trail_diff/branch_snapshot_refresher.rbs
138
149
  - sig/generated/paper_trail_diff/collection_comparator.rbs
139
150
  - sig/generated/paper_trail_diff/collection_identity_index.rbs
@@ -172,6 +183,7 @@ files:
172
183
  - sig/generated/paper_trail_diff/traversal.rbs
173
184
  - sig/generated/paper_trail_diff/traversal_emitter.rbs
174
185
  - sig/generated/paper_trail_diff/traversal_entry.rbs
186
+ - sig/generated/paper_trail_diff/traversal_preparer.rbs
175
187
  - sig/generated/paper_trail_diff/value_objects.rbs
176
188
  - sig/generated/paper_trail_diff/version.rbs
177
189
  - sig/generated/paper_trail_diff/version_association_candidate_scope.rbs
@@ -182,11 +194,11 @@ licenses:
182
194
  metadata:
183
195
  allowed_push_host: https://rubygems.org
184
196
  bug_tracker_uri: https://github.com/aheathwilliams/paper_trail_diff/issues
185
- changelog_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.3.1/CHANGELOG.md
186
- documentation_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.3.1/README.md
197
+ changelog_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.5.0/CHANGELOG.md
198
+ documentation_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.5.0/README.md
187
199
  homepage_uri: https://github.com/aheathwilliams/paper_trail_diff
188
200
  rubygems_mfa_required: 'true'
189
- source_code_uri: https://github.com/aheathwilliams/paper_trail_diff/tree/v0.3.1
201
+ source_code_uri: https://github.com/aheathwilliams/paper_trail_diff/tree/v0.5.0
190
202
  rdoc_options: []
191
203
  require_paths:
192
204
  - lib