paper_trail_diff 0.8.0 → 0.9.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 +18 -0
- data/README.md +29 -1
- data/lib/paper_trail_diff/diagnostics.rb +7 -23
- data/lib/paper_trail_diff/instrumentation.rb +8 -0
- data/lib/paper_trail_diff/paper_trail_adapter.rb +22 -0
- data/lib/paper_trail_diff/support.rb +9 -0
- data/lib/paper_trail_diff/version.rb +1 -1
- data/lib/paper_trail_diff/version_sequence_diagnostics.rb +82 -0
- data/lib/paper_trail_diff.rb +1 -0
- data/sig/generated/paper_trail_diff/diagnostics.rbs +1 -7
- data/sig/generated/paper_trail_diff/instrumentation.rbs +5 -0
- data/sig/generated/paper_trail_diff/paper_trail_adapter.rbs +8 -0
- data/sig/generated/paper_trail_diff/support.rbs +7 -0
- data/sig/generated/paper_trail_diff/version_sequence_diagnostics.rbs +39 -0
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ee80500dbeb48421e7b0e0766a5f5559b73aa71528360a5f1a16866f9e6ccfa
|
|
4
|
+
data.tar.gz: 6692d3fd2d725918e16da15b4d39312b5e1a42deba3aa8e50a269abfd9fc6bd9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f809075c65c923ca0dd828e8337477d8461dfa13b2de537a9f99548f0826f867379a33c8bf4a5061476dabd1685829adc5ab21e07052a4d40ebfff4736a44946
|
|
7
|
+
data.tar.gz: 6212fab6601c900b2701a9401e7e9b66c5236f12da0340788f0641efef759340a29ea6f95e7b51d86c2792d847f5553db8f30d7c96e4370e37ceec0b8a227656
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file. The
|
|
4
4
|
project follows [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.9.0] - 2026-08-14
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Report versions that share a timestamp, which hides any association change
|
|
11
|
+
between them: PT-AT records membership per version but resolves it by
|
|
12
|
+
timestamp, so such a pair is indistinguishable even when sequential ids order
|
|
13
|
+
it correctly. `diagnose` reports `:tied_version_timestamps` as a warning when
|
|
14
|
+
`associations:` are selected, and a comparison in that state emits
|
|
15
|
+
`ambiguous_association_boundary.paper_trail_diff`. It warns rather than
|
|
16
|
+
raising because the result may be perfectly correct — if nothing associated
|
|
17
|
+
changed, nothing was lost — and the gem cannot distinguish the cases, since
|
|
18
|
+
not seeing the change is the symptom.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Link the demo application from the README now that it is public.
|
|
23
|
+
|
|
6
24
|
## [0.8.0] - 2026-08-12
|
|
7
25
|
|
|
8
26
|
### Added
|
data/README.md
CHANGED
|
@@ -29,7 +29,10 @@ which fetches what it needs on first run:
|
|
|
29
29
|
ruby demo.rb
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
Then start with the copyable [Quickstart](QUICKSTART.md)
|
|
32
|
+
Then start with the copyable [Quickstart](QUICKSTART.md), or browse
|
|
33
|
+
[the demo application](https://github.com/aheathwilliams/paper_trail_summary_test_app)
|
|
34
|
+
— a small Rails app that installs a published release and exercises scalar,
|
|
35
|
+
nested, through-association, and HABTM history against it.
|
|
33
36
|
|
|
34
37
|
## Installation
|
|
35
38
|
|
|
@@ -124,6 +127,31 @@ running rather than after a surprise.
|
|
|
124
127
|
Either half alone is fine. Sequential ids order tied timestamps correctly, and
|
|
125
128
|
distinct timestamps never reach the fallback.
|
|
126
129
|
|
|
130
|
+
### Association changes across a shared timestamp
|
|
131
|
+
|
|
132
|
+
Sequential ids recover the *order* of tied versions, but not their association
|
|
133
|
+
state. PT-AT records association membership per version and resolves it by
|
|
134
|
+
timestamp, so two versions sharing one are indistinguishable for that purpose:
|
|
135
|
+
**an association change between them is invisible.** It is not reported as
|
|
136
|
+
absent — the association simply does not appear in the diff.
|
|
137
|
+
|
|
138
|
+
Unlike an unorderable sequence this is not always wrong. If nothing associated
|
|
139
|
+
changed between the two versions, the result is correct, and the gem cannot
|
|
140
|
+
tell the two cases apart, because not seeing the change is the symptom. So it
|
|
141
|
+
does not raise. Instead:
|
|
142
|
+
|
|
143
|
+
- `diagnose` reports `:tied_version_timestamps` as a **warning** whenever
|
|
144
|
+
`associations:` are selected and versions in range share a timestamp.
|
|
145
|
+
- a comparison in that state emits
|
|
146
|
+
`ambiguous_association_boundary.paper_trail_diff` through ActiveSupport
|
|
147
|
+
notifications, carrying the two version ids and the shared timestamp. Nothing
|
|
148
|
+
is logged; subscribe if you want it surfaced.
|
|
149
|
+
|
|
150
|
+
Writing several versions inside one clock tick is easy to do — a service object
|
|
151
|
+
that touches a record and its children in quick succession will manage it — so
|
|
152
|
+
this is worth checking before trusting an association history. Recording
|
|
153
|
+
versions at sub-second precision separates them.
|
|
154
|
+
|
|
127
155
|
## Choosing an entry point
|
|
128
156
|
|
|
129
157
|
| You need | Call |
|
|
@@ -79,7 +79,7 @@ module PaperTrailDiff
|
|
|
79
79
|
# Runs whether or not associations are selected: unorderable versions
|
|
80
80
|
# corrupt a scalar timeline just as surely, and a report that inspected
|
|
81
81
|
# nothing has no business answering `ok?`.
|
|
82
|
-
|
|
82
|
+
inspect_version_sequence
|
|
83
83
|
return DiagnosticReport.new(issues: @issues) if @tree.empty?
|
|
84
84
|
|
|
85
85
|
unless association_tracking_available?
|
|
@@ -136,29 +136,13 @@ module PaperTrailDiff
|
|
|
136
136
|
inspect_transaction_metadata(paths)
|
|
137
137
|
end
|
|
138
138
|
|
|
139
|
-
# Ordering falls back to the id when timestamps tie, which only recovers the
|
|
140
|
-
# real sequence for ids that increase with insertion. Reported before a run
|
|
141
|
-
# rather than after a wrong answer.
|
|
142
139
|
#: () -> void
|
|
143
|
-
def
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
nil
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
#: () -> Array[untyped]
|
|
153
|
-
def ordered_range_versions
|
|
154
|
-
bounds = [@from_version.created_at, @to_version.created_at].compact.sort
|
|
155
|
-
return [] unless bounds.length == 2
|
|
156
|
-
|
|
157
|
-
@from_version.class
|
|
158
|
-
.where(item_type: @from_version.item_type, item_id: @from_version.item_id)
|
|
159
|
-
.where(created_at: bounds.first..bounds.last)
|
|
160
|
-
.to_a
|
|
161
|
-
.sort_by { |version| Support.chronological_version_key(version) }
|
|
140
|
+
def inspect_version_sequence
|
|
141
|
+
@issues.concat(
|
|
142
|
+
VersionSequenceDiagnostics.new(
|
|
143
|
+
@from_version, @to_version, associations_selected: !@tree.empty?
|
|
144
|
+
).call
|
|
145
|
+
)
|
|
162
146
|
end
|
|
163
147
|
|
|
164
148
|
#: (untyped) -> void
|
|
@@ -19,6 +19,14 @@ module PaperTrailDiff
|
|
|
19
19
|
)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
# Reports a condition rather than timing work: nothing failed, but the
|
|
23
|
+
# result may be incomplete and only the application can judge that.
|
|
24
|
+
#: (String | Symbol, Hash[Symbol, untyped]) -> void
|
|
25
|
+
def notify(event, payload)
|
|
26
|
+
instrument(event, payload) { nil }
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
|
|
22
30
|
#: (association_paths: Array[String], reload_live_endpoints: bool) -> Hash[Symbol, untyped]
|
|
23
31
|
def comparison_payload(association_paths:, reload_live_endpoints:)
|
|
24
32
|
{
|
|
@@ -33,6 +33,7 @@ module PaperTrailDiff
|
|
|
33
33
|
payload = @instrumentation_payload.merge(comparison_count: 1)
|
|
34
34
|
Instrumentation.instrument('compare', payload) do
|
|
35
35
|
Endpoint.validate_pair!(from_endpoint, to_endpoint)
|
|
36
|
+
notify_ambiguous_association_boundary(from_endpoint, to_endpoint)
|
|
36
37
|
Engine.compare(snapshot_for_endpoint(from_endpoint), snapshot_for_endpoint(to_endpoint))
|
|
37
38
|
end
|
|
38
39
|
end
|
|
@@ -141,6 +142,27 @@ module PaperTrailDiff
|
|
|
141
142
|
).analyze
|
|
142
143
|
end
|
|
143
144
|
|
|
145
|
+
# Association membership is resolved by timestamp, so endpoints sharing one
|
|
146
|
+
# cannot be told apart and any association change between them is invisible.
|
|
147
|
+
# The result may still be correct -- nothing associated may have changed --
|
|
148
|
+
# and the gem cannot tell which, since not seeing the change is the symptom.
|
|
149
|
+
# So it reports the condition and leaves the judgement to the application.
|
|
150
|
+
#: (untyped, untyped) -> void
|
|
151
|
+
def notify_ambiguous_association_boundary(from_endpoint, to_endpoint)
|
|
152
|
+
return if @association_tree.empty?
|
|
153
|
+
return unless Endpoint.version?(from_endpoint) && Endpoint.version?(to_endpoint)
|
|
154
|
+
return unless from_endpoint.created_at == to_endpoint.created_at
|
|
155
|
+
|
|
156
|
+
Instrumentation.notify(
|
|
157
|
+
'ambiguous_association_boundary',
|
|
158
|
+
@instrumentation_payload.merge(
|
|
159
|
+
item_type: from_endpoint.item_type.to_s,
|
|
160
|
+
version_ids: [from_endpoint.id, to_endpoint.id].freeze,
|
|
161
|
+
recorded_at: from_endpoint.created_at
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
end
|
|
165
|
+
|
|
144
166
|
# `close_on:` names what ends a wall-clock window, so it is meaningless for a
|
|
145
167
|
# range whose endpoints the caller already gave explicitly.
|
|
146
168
|
#: (Symbol?, untyped) -> bool
|
|
@@ -72,6 +72,15 @@ module PaperTrailDiff
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
# Versions sharing a timestamp, whether or not their ids order them. PT-AT
|
|
76
|
+
# indexes association membership per version but resolves it by timestamp,
|
|
77
|
+
# so association state cannot be told apart across such a pair even when the
|
|
78
|
+
# scalar sequence is perfectly recoverable.
|
|
79
|
+
#: (Array[untyped]) -> Array[untyped]?
|
|
80
|
+
def tied_timestamp_pair(versions)
|
|
81
|
+
versions.each_cons(2).find { |left, right| left.created_at == right.created_at }
|
|
82
|
+
end
|
|
83
|
+
|
|
75
84
|
#: (untyped) -> bool
|
|
76
85
|
def sequential_id?(id)
|
|
77
86
|
id.is_a?(Integer) || id.to_s.match?(/\A\d+\z/)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
3
|
+
|
|
4
|
+
module PaperTrailDiff
|
|
5
|
+
# Checks the recorded sequence itself, before any question of association
|
|
6
|
+
# setup: whether the versions can be ordered at all, and whether timestamps
|
|
7
|
+
# they share hide changes that ordering alone cannot recover.
|
|
8
|
+
class VersionSequenceDiagnostics
|
|
9
|
+
#: (untyped, untyped, ?associations_selected: bool) -> void
|
|
10
|
+
def initialize(from_version, to_version, associations_selected: false)
|
|
11
|
+
@from_version = from_version
|
|
12
|
+
@to_version = to_version
|
|
13
|
+
@associations_selected = associations_selected
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#: () -> Array[DiagnosticIssue]
|
|
17
|
+
def call
|
|
18
|
+
versions = ordered_range_versions
|
|
19
|
+
issues = [] #: Array[DiagnosticIssue?]
|
|
20
|
+
issues << unorderable(versions)
|
|
21
|
+
issues << tied_timestamps(versions) if @associations_selected
|
|
22
|
+
issues.compact
|
|
23
|
+
rescue StandardError
|
|
24
|
+
[]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# @rbs @from_version: untyped
|
|
30
|
+
# @rbs @to_version: untyped
|
|
31
|
+
# @rbs @associations_selected: bool
|
|
32
|
+
|
|
33
|
+
# Ordering falls back to the id when timestamps tie, which only recovers the
|
|
34
|
+
# real sequence for ids that increase with insertion. Reported before a run
|
|
35
|
+
# rather than after a wrong answer.
|
|
36
|
+
#: (Array[untyped]) -> DiagnosticIssue?
|
|
37
|
+
def unorderable(versions)
|
|
38
|
+
pair = Support.ambiguous_pair(versions)
|
|
39
|
+
return unless pair
|
|
40
|
+
|
|
41
|
+
DiagnosticIssue.new(
|
|
42
|
+
severity: :error,
|
|
43
|
+
code: :ambiguous_version_order,
|
|
44
|
+
message: Support.ambiguous_message(pair),
|
|
45
|
+
version_id: pair.first.id
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Association membership is recorded per version but resolved by timestamp,
|
|
50
|
+
# so a tie hides any association change across that pair. Unlike an
|
|
51
|
+
# unorderable sequence this is not always wrong: if nothing associated
|
|
52
|
+
# changed between them the result is correct, and the gem cannot tell which
|
|
53
|
+
# it is, because not seeing the change is the symptom. So it warns.
|
|
54
|
+
#: (Array[untyped]) -> DiagnosticIssue?
|
|
55
|
+
def tied_timestamps(versions)
|
|
56
|
+
pair = Support.tied_timestamp_pair(versions)
|
|
57
|
+
return unless pair
|
|
58
|
+
|
|
59
|
+
left, right = pair
|
|
60
|
+
DiagnosticIssue.new(
|
|
61
|
+
severity: :warning,
|
|
62
|
+
code: :tied_version_timestamps,
|
|
63
|
+
message: "versions #{left.id.inspect} and #{right.id.inspect} share the timestamp " \
|
|
64
|
+
"#{left.created_at.inspect}, so association changes between them cannot " \
|
|
65
|
+
'be detected; record versions at sub-second precision to separate them',
|
|
66
|
+
version_id: left.id
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
#: () -> Array[untyped]
|
|
71
|
+
def ordered_range_versions
|
|
72
|
+
bounds = [@from_version.created_at, @to_version.created_at].compact.sort
|
|
73
|
+
return [] unless bounds.length == 2
|
|
74
|
+
|
|
75
|
+
@from_version.class
|
|
76
|
+
.where(item_type: @from_version.item_type, item_id: @from_version.item_id)
|
|
77
|
+
.where(created_at: bounds.first..bounds.last)
|
|
78
|
+
.to_a
|
|
79
|
+
.sort_by { |version| Support.chronological_version_key(version) }
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/paper_trail_diff.rb
CHANGED
|
@@ -65,6 +65,7 @@ require_relative 'paper_trail_diff/activity_root_steps'
|
|
|
65
65
|
require_relative 'paper_trail_diff/analysis_batch'
|
|
66
66
|
require_relative 'paper_trail_diff/batched_root_analyzer'
|
|
67
67
|
require_relative 'paper_trail_diff/version_range'
|
|
68
|
+
require_relative 'paper_trail_diff/version_sequence_diagnostics'
|
|
68
69
|
require_relative 'paper_trail_diff/time_range'
|
|
69
70
|
require_relative 'paper_trail_diff/time_version_range'
|
|
70
71
|
require_relative 'paper_trail_diff/timeline_range'
|
|
@@ -67,14 +67,8 @@ module PaperTrailDiff
|
|
|
67
67
|
# : (Array[Array[untyped]]) -> void
|
|
68
68
|
def inspect_habtm: (Array[Array[untyped]]) -> void
|
|
69
69
|
|
|
70
|
-
# Ordering falls back to the id when timestamps tie, which only recovers the
|
|
71
|
-
# real sequence for ids that increase with insertion. Reported before a run
|
|
72
|
-
# rather than after a wrong answer.
|
|
73
70
|
# : () -> void
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
# : () -> Array[untyped]
|
|
77
|
-
def ordered_range_versions: () -> Array[untyped]
|
|
71
|
+
def inspect_version_sequence: () -> void
|
|
78
72
|
|
|
79
73
|
# : (untyped) -> void
|
|
80
74
|
def inspect_checkpoint_timestamp: (untyped) -> void
|
|
@@ -6,6 +6,11 @@ module PaperTrailDiff
|
|
|
6
6
|
# : (String | Symbol, Hash[Symbol, untyped]) { () -> untyped } -> untyped
|
|
7
7
|
def self?.instrument: (String | Symbol, Hash[Symbol, untyped]) { () -> untyped } -> untyped
|
|
8
8
|
|
|
9
|
+
# Reports a condition rather than timing work: nothing failed, but the
|
|
10
|
+
# result may be incomplete and only the application can judge that.
|
|
11
|
+
# : (String | Symbol, Hash[Symbol, untyped]) -> void
|
|
12
|
+
def self?.notify: (String | Symbol, Hash[Symbol, untyped]) -> void
|
|
13
|
+
|
|
9
14
|
# : (association_paths: Array[String], reload_live_endpoints: bool) -> Hash[Symbol, untyped]
|
|
10
15
|
def self?.comparison_payload: (association_paths: Array[String], reload_live_endpoints: bool) -> Hash[Symbol, untyped]
|
|
11
16
|
end
|
|
@@ -59,6 +59,14 @@ module PaperTrailDiff
|
|
|
59
59
|
# : (untyped, from: untyped, to: untyped, within: untyped, version_scope: untyped, live_endpoint: untyped, ?snapshots: bool) -> Analysis
|
|
60
60
|
def analyze_activity: (untyped, from: untyped, to: untyped, within: untyped, version_scope: untyped, live_endpoint: untyped, ?snapshots: bool) -> Analysis
|
|
61
61
|
|
|
62
|
+
# Association membership is resolved by timestamp, so endpoints sharing one
|
|
63
|
+
# cannot be told apart and any association change between them is invisible.
|
|
64
|
+
# The result may still be correct -- nothing associated may have changed --
|
|
65
|
+
# and the gem cannot tell which, since not seeing the change is the symptom.
|
|
66
|
+
# So it reports the condition and leaves the judgement to the application.
|
|
67
|
+
# : (untyped, untyped) -> void
|
|
68
|
+
def notify_ambiguous_association_boundary: (untyped, untyped) -> void
|
|
69
|
+
|
|
62
70
|
# `close_on:` names what ends a wall-clock window, so it is meaningless for a
|
|
63
71
|
# range whose endpoints the caller already gave explicitly.
|
|
64
72
|
# : (Symbol?, untyped) -> bool
|
|
@@ -25,6 +25,13 @@ module PaperTrailDiff
|
|
|
25
25
|
# : (Array[untyped]) -> Array[untyped]?
|
|
26
26
|
def self?.ambiguous_pair: (Array[untyped]) -> Array[untyped]?
|
|
27
27
|
|
|
28
|
+
# Versions sharing a timestamp, whether or not their ids order them. PT-AT
|
|
29
|
+
# indexes association membership per version but resolves it by timestamp,
|
|
30
|
+
# so association state cannot be told apart across such a pair even when the
|
|
31
|
+
# scalar sequence is perfectly recoverable.
|
|
32
|
+
# : (Array[untyped]) -> Array[untyped]?
|
|
33
|
+
def self?.tied_timestamp_pair: (Array[untyped]) -> Array[untyped]?
|
|
34
|
+
|
|
28
35
|
# : (untyped) -> bool
|
|
29
36
|
def self?.sequential_id?: (untyped) -> bool
|
|
30
37
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Generated from lib/paper_trail_diff/version_sequence_diagnostics.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module PaperTrailDiff
|
|
4
|
+
# Checks the recorded sequence itself, before any question of association
|
|
5
|
+
# setup: whether the versions can be ordered at all, and whether timestamps
|
|
6
|
+
# they share hide changes that ordering alone cannot recover.
|
|
7
|
+
class VersionSequenceDiagnostics
|
|
8
|
+
# : (untyped, untyped, ?associations_selected: bool) -> void
|
|
9
|
+
def initialize: (untyped, untyped, ?associations_selected: bool) -> void
|
|
10
|
+
|
|
11
|
+
# : () -> Array[DiagnosticIssue]
|
|
12
|
+
def call: () -> Array[DiagnosticIssue]
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
@associations_selected: bool
|
|
17
|
+
|
|
18
|
+
@from_version: untyped
|
|
19
|
+
|
|
20
|
+
@to_version: untyped
|
|
21
|
+
|
|
22
|
+
# Ordering falls back to the id when timestamps tie, which only recovers the
|
|
23
|
+
# real sequence for ids that increase with insertion. Reported before a run
|
|
24
|
+
# rather than after a wrong answer.
|
|
25
|
+
# : (Array[untyped]) -> DiagnosticIssue?
|
|
26
|
+
def unorderable: (Array[untyped]) -> DiagnosticIssue?
|
|
27
|
+
|
|
28
|
+
# Association membership is recorded per version but resolved by timestamp,
|
|
29
|
+
# so a tie hides any association change across that pair. Unlike an
|
|
30
|
+
# unorderable sequence this is not always wrong: if nothing associated
|
|
31
|
+
# changed between them the result is correct, and the gem cannot tell which
|
|
32
|
+
# it is, because not seeing the change is the symptom. So it warns.
|
|
33
|
+
# : (Array[untyped]) -> DiagnosticIssue?
|
|
34
|
+
def tied_timestamps: (Array[untyped]) -> DiagnosticIssue?
|
|
35
|
+
|
|
36
|
+
# : () -> Array[untyped]
|
|
37
|
+
def ordered_range_versions: () -> Array[untyped]
|
|
38
|
+
end
|
|
39
|
+
end
|
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.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex Williams
|
|
@@ -118,6 +118,7 @@ files:
|
|
|
118
118
|
- lib/paper_trail_diff/version_association_candidate_scope.rb
|
|
119
119
|
- lib/paper_trail_diff/version_range.rb
|
|
120
120
|
- lib/paper_trail_diff/version_scope_filter.rb
|
|
121
|
+
- lib/paper_trail_diff/version_sequence_diagnostics.rb
|
|
121
122
|
- sig/generated/paper_trail_diff.rbs
|
|
122
123
|
- sig/generated/paper_trail_diff/activity_belongs_to_event_applier.rbs
|
|
123
124
|
- sig/generated/paper_trail_diff/activity_boundary.rbs
|
|
@@ -194,17 +195,18 @@ files:
|
|
|
194
195
|
- sig/generated/paper_trail_diff/version_association_candidate_scope.rbs
|
|
195
196
|
- sig/generated/paper_trail_diff/version_range.rbs
|
|
196
197
|
- sig/generated/paper_trail_diff/version_scope_filter.rbs
|
|
198
|
+
- sig/generated/paper_trail_diff/version_sequence_diagnostics.rbs
|
|
197
199
|
homepage: https://github.com/aheathwilliams/paper_trail_diff
|
|
198
200
|
licenses:
|
|
199
201
|
- MIT
|
|
200
202
|
metadata:
|
|
201
203
|
allowed_push_host: https://rubygems.org
|
|
202
204
|
bug_tracker_uri: https://github.com/aheathwilliams/paper_trail_diff/issues
|
|
203
|
-
changelog_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.
|
|
204
|
-
documentation_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.
|
|
205
|
+
changelog_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.9.0/CHANGELOG.md
|
|
206
|
+
documentation_uri: https://github.com/aheathwilliams/paper_trail_diff/blob/v0.9.0/README.md
|
|
205
207
|
homepage_uri: https://github.com/aheathwilliams/paper_trail_diff
|
|
206
208
|
rubygems_mfa_required: 'true'
|
|
207
|
-
source_code_uri: https://github.com/aheathwilliams/paper_trail_diff/tree/v0.
|
|
209
|
+
source_code_uri: https://github.com/aheathwilliams/paper_trail_diff/tree/v0.9.0
|
|
208
210
|
rdoc_options: []
|
|
209
211
|
require_paths:
|
|
210
212
|
- lib
|