paper_trail_diff 0.1.0 → 0.2.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.
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module PaperTrailDiff
5
+ # Walks nested state included in an added, removed, or replaced record snapshot.
6
+ class SnapshotTraversal < TraversalEmitter
7
+ #: (RecordSnapshot, association_path: traversal_association_path, record_path: traversal_record_path, state: traversal_state, ?association_kind: Symbol?, ?include_record: bool) -> void
8
+ def call( # rubocop:disable Metrics/ParameterLists
9
+ snapshot,
10
+ association_path:,
11
+ record_path:,
12
+ state:,
13
+ association_kind: nil,
14
+ include_record: true
15
+ )
16
+ if include_record
17
+ emit_record(snapshot, association_path, record_path, state, association_kind)
18
+ end
19
+ emit_attributes(snapshot, association_path, record_path, state, association_kind)
20
+ emit_associations(snapshot, association_path, record_path, state)
21
+ end
22
+
23
+ private
24
+
25
+ #: (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
26
+ def emit_record(snapshot, association_path, record_path, state, association_kind)
27
+ emit(
28
+ kind: :record_included,
29
+ context: :included_state,
30
+ association_path: association_path,
31
+ record_path: record_path,
32
+ association_kind: association_kind,
33
+ state: state,
34
+ value: snapshot.reference
35
+ )
36
+ end
37
+
38
+ #: (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
39
+ def emit_attributes(snapshot, association_path, record_path, state, association_kind)
40
+ snapshot.attributes.each do |name, value|
41
+ emit_attribute(name, value, association_path, record_path, state, association_kind)
42
+ end
43
+ end
44
+
45
+ #: (String, untyped, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
46
+ def emit_attribute( # rubocop:disable Metrics/ParameterLists
47
+ name, value, association_path, record_path, state, association_kind
48
+ )
49
+ emit(
50
+ kind: :attribute_included,
51
+ context: :included_state,
52
+ association_path: association_path,
53
+ record_path: record_path,
54
+ association_kind: association_kind,
55
+ state: state,
56
+ attribute: name,
57
+ value: value
58
+ )
59
+ end
60
+
61
+ #: (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
62
+ def emit_associations(snapshot, association_path, record_path, state)
63
+ snapshot.associations.each do |name, association|
64
+ child_path = association_path + [name]
65
+ emit_association(association, child_path, record_path, state)
66
+ emit_association_records(association, child_path, record_path, state)
67
+ end
68
+ end
69
+
70
+ #: (AssociationSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
71
+ def emit_association(association, association_path, record_path, state)
72
+ emit(
73
+ kind: :association_included,
74
+ context: :included_state,
75
+ association_path: association_path,
76
+ record_path: record_path,
77
+ association_kind: association.kind,
78
+ state: state,
79
+ value: association
80
+ )
81
+ end
82
+
83
+ #: (AssociationSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
84
+ def emit_association_records(association, association_path, record_path, state)
85
+ association.records.each do |snapshot|
86
+ call(
87
+ snapshot,
88
+ association_path: association_path,
89
+ record_path: record_path + [snapshot.reference],
90
+ state: state,
91
+ association_kind: association.kind
92
+ )
93
+ end
94
+ end
95
+ end
96
+ private_constant :SnapshotTraversal
97
+ end
@@ -6,16 +6,25 @@ module PaperTrailDiff
6
6
  class Step
7
7
  attr_reader :from_version #: untyped
8
8
  attr_reader :to_version #: untyped
9
+ attr_reader :from_boundary #: ActivityBoundary
10
+ attr_reader :to_boundary #: ActivityBoundary
9
11
  attr_reader :diff #: Diff
10
12
 
11
13
  #: (from_version: untyped, to_version: untyped, diff: Diff) -> void
12
14
  def initialize(from_version:, to_version:, diff:)
13
15
  @from_version = from_version
14
16
  @to_version = to_version
17
+ @from_boundary = ActivityBoundary.from_version(from_version)
18
+ @to_boundary = ActivityBoundary.from_version(to_version)
15
19
  @diff = diff
16
20
  freeze
17
21
  end
18
22
 
23
+ #: () -> bool
24
+ def empty?
25
+ diff.empty?
26
+ end
27
+
19
28
  #: () -> Hash[Symbol, untyped]
20
29
  def to_h
21
30
  {
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module PaperTrailDiff
5
+ # Coordinates root lifecycle, scalar, and association traversal.
6
+ class DiffTraversal < TraversalEmitter
7
+ #: (Diff, ^(TraversalEntry) -> void) -> void
8
+ def initialize(diff, receiver)
9
+ super(receiver)
10
+ @diff = diff
11
+ @associations = AssociationDiffTraversal.new(receiver)
12
+ @snapshots = SnapshotTraversal.new(receiver)
13
+ end
14
+
15
+ #: () -> void
16
+ def call
17
+ walk_presence_change
18
+ @associations.attributes(
19
+ @diff.attributes,
20
+ association_path: [],
21
+ record_path: [],
22
+ association_kind: nil
23
+ )
24
+ @associations.call(@diff.associations, association_path: [], record_path: [])
25
+ end
26
+
27
+ private
28
+
29
+ # @rbs @diff: Diff
30
+ # @rbs @associations: AssociationDiffTraversal
31
+ # @rbs @snapshots: SnapshotTraversal
32
+
33
+ #: () -> void
34
+ def walk_presence_change
35
+ change = @diff.record_presence_change
36
+ return unless change
37
+
38
+ emit(
39
+ kind: :record_presence_changed,
40
+ context: :change,
41
+ association_path: [],
42
+ record_path: [],
43
+ value: change
44
+ )
45
+ walk_presence_snapshot(change.from, :before)
46
+ walk_presence_snapshot(change.to, :after)
47
+ end
48
+
49
+ #: (RecordSnapshot?, traversal_state) -> void
50
+ def walk_presence_snapshot(snapshot, state)
51
+ return unless snapshot
52
+
53
+ @snapshots.call(snapshot, association_path: [], record_path: [], state: state)
54
+ end
55
+ end
56
+ private_constant :DiffTraversal
57
+
58
+ # The complete structured difference between two normalized endpoints.
59
+ class Diff
60
+ # Walks semantic changes and the nested state carried by added or removed records.
61
+ # @rbs () { (TraversalEntry) -> void } -> Diff
62
+ # | () -> Enumerator[TraversalEntry, Diff]
63
+ def each_entry(&receiver)
64
+ return enum_for(:each_entry) unless receiver
65
+
66
+ DiffTraversal.new(self, receiver).call
67
+ self
68
+ end
69
+
70
+ # Walks only semantic changes, excluding snapshot state included for context.
71
+ # @rbs () { (TraversalEntry) -> void } -> Diff
72
+ # | () -> Enumerator[TraversalEntry, Diff]
73
+ def each_change(&receiver)
74
+ return enum_for(:each_change) unless receiver
75
+
76
+ each_entry { |entry| receiver.call(entry) if entry.change? }
77
+ self
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module PaperTrailDiff
5
+ # Shared entry construction for internal traversal collaborators.
6
+ class TraversalEmitter
7
+ #: (^(TraversalEntry) -> void) -> void
8
+ def initialize(receiver)
9
+ @receiver = receiver
10
+ end
11
+
12
+ private
13
+
14
+ # @rbs @receiver: ^(TraversalEntry) -> void
15
+
16
+ #: (kind: Symbol, context: traversal_context, association_path: traversal_association_path, record_path: traversal_record_path, value: untyped, ?association_kind: Symbol?, ?state: traversal_state?, ?attribute: String?) -> void
17
+ def emit( # rubocop:disable Metrics/ParameterLists
18
+ kind:,
19
+ context:,
20
+ association_path:,
21
+ record_path:,
22
+ value:,
23
+ association_kind: nil,
24
+ state: nil,
25
+ attribute: nil
26
+ )
27
+ @receiver.call(
28
+ TraversalEntry.new(
29
+ kind: kind,
30
+ context: context,
31
+ association_path: association_path,
32
+ record_path: record_path,
33
+ association_kind: association_kind,
34
+ state: state,
35
+ attribute: attribute,
36
+ value: value
37
+ )
38
+ )
39
+ end
40
+ end
41
+ private_constant :TraversalEmitter
42
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module PaperTrailDiff
5
+ # One immutable location and value emitted while walking a Diff tree.
6
+ class TraversalEntry
7
+ CONTEXTS = %i[change included_state].freeze
8
+ STATES = %i[before after].freeze
9
+ private_constant :CONTEXTS, :STATES
10
+
11
+ attr_reader :kind #: Symbol
12
+ attr_reader :context #: traversal_context
13
+ attr_reader :association_path #: traversal_association_path
14
+ attr_reader :record_path #: traversal_record_path
15
+ attr_reader :association_kind #: Symbol?
16
+ attr_reader :state #: traversal_state?
17
+ attr_reader :attribute #: String?
18
+ attr_reader :value #: untyped
19
+
20
+ #: (kind: Symbol, context: traversal_context, ?association_path: traversal_association_path, ?record_path: traversal_record_path, ?association_kind: Symbol?, ?state: traversal_state?, ?attribute: String?, ?value: untyped) -> void
21
+ def initialize( # rubocop:disable Metrics/ParameterLists
22
+ kind:,
23
+ context:,
24
+ association_path: [],
25
+ record_path: [],
26
+ association_kind: nil,
27
+ state: nil,
28
+ attribute: nil,
29
+ value: nil
30
+ )
31
+ validate!(context, state)
32
+ @kind = kind
33
+ @context = context
34
+ @association_path = immutable_names(association_path)
35
+ @record_path = Support.immutable_copy(record_path)
36
+ @association_kind = association_kind
37
+ @state = state
38
+ @attribute = Support.immutable_copy(attribute&.to_s)
39
+ @value = Support.immutable_copy(value)
40
+ freeze
41
+ end
42
+
43
+ #: () -> bool
44
+ def change?
45
+ context == :change
46
+ end
47
+
48
+ #: () -> bool
49
+ def included_state?
50
+ context == :included_state
51
+ end
52
+
53
+ #: () -> String?
54
+ def association
55
+ association_path.last
56
+ end
57
+
58
+ #: () -> RecordReference?
59
+ def record
60
+ record_path.last
61
+ end
62
+
63
+ #: () -> Hash[Symbol, untyped]
64
+ def to_h
65
+ {
66
+ kind: kind,
67
+ context: context,
68
+ association_path: Support.serialize(association_path),
69
+ record_path: Support.serialize(record_path),
70
+ association_kind: association_kind,
71
+ state: state,
72
+ attribute: attribute,
73
+ value: Support.serialize(value)
74
+ }
75
+ end
76
+
77
+ private
78
+
79
+ #: (Symbol, Symbol?) -> void
80
+ def validate!(candidate_context, candidate_state)
81
+ unless CONTEXTS.include?(candidate_context)
82
+ raise ArgumentError, "unsupported traversal context: #{candidate_context.inspect}"
83
+ end
84
+ return if candidate_state.nil? || STATES.include?(candidate_state)
85
+
86
+ raise ArgumentError, "unsupported traversal state: #{candidate_state.inspect}"
87
+ end
88
+
89
+ #: (traversal_association_path) -> traversal_association_path
90
+ def immutable_names(names)
91
+ names.map { |name| Support.immutable_copy(name.to_s) }.freeze
92
+ end
93
+ end
94
+ end
@@ -2,5 +2,5 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  module PaperTrailDiff
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
@@ -13,6 +13,11 @@ require_relative 'paper_trail_diff/association_discovery'
13
13
  require_relative 'paper_trail_diff/diagnostics'
14
14
  require_relative 'paper_trail_diff/snapshot'
15
15
  require_relative 'paper_trail_diff/value_objects'
16
+ require_relative 'paper_trail_diff/traversal_entry'
17
+ require_relative 'paper_trail_diff/traversal_emitter'
18
+ require_relative 'paper_trail_diff/snapshot_traversal'
19
+ require_relative 'paper_trail_diff/association_diff_traversal'
20
+ require_relative 'paper_trail_diff/traversal'
16
21
  require_relative 'paper_trail_diff/engine'
17
22
  require_relative 'paper_trail_diff/historical_association_reifier'
18
23
  require_relative 'paper_trail_diff/prepared_record_index'
@@ -27,8 +32,8 @@ require_relative 'paper_trail_diff/timeline_snapshot_provider'
27
32
  require_relative 'paper_trail_diff/activity_event_snapshot_refresher'
28
33
  require_relative 'paper_trail_diff/activity_root_snapshot_refresher'
29
34
  require_relative 'paper_trail_diff/branch_snapshot_refresher'
30
- require_relative 'paper_trail_diff/step'
31
35
  require_relative 'paper_trail_diff/activity_boundary'
36
+ require_relative 'paper_trail_diff/step'
32
37
  require_relative 'paper_trail_diff/analysis'
33
38
  require_relative 'paper_trail_diff/version_range'
34
39
  require_relative 'paper_trail_diff/timeline_builder'
@@ -50,6 +55,10 @@ require_relative 'paper_trail_diff/paper_trail_adapter'
50
55
  # type identity = Array[untyped]
51
56
  # type ignore_option = Array[String | Symbol] | Hash[String | Symbol, untyped]
52
57
  # type reference_key = :type | :id | "type" | "id"
58
+ # type traversal_context = :change | :included_state
59
+ # type traversal_state = :before | :after
60
+ # type traversal_association_path = Array[String]
61
+ # type traversal_record_path = Array[RecordReference]
53
62
  # end
54
63
 
55
64
  # Structured version comparison for PaperTrail.
@@ -13,14 +13,26 @@ module PaperTrailDiff
13
13
 
14
14
  attr_reader recorded_at: untyped
15
15
 
16
+ attr_reader event: String?
17
+
18
+ attr_reader whodunnit: untyped
19
+
20
+ attr_reader record: RecordReference
21
+
16
22
  # : (untyped) -> ActivityBoundary
17
23
  def self.from_version: (untyped) -> ActivityBoundary
18
24
 
19
25
  # : (untyped, captured_at: untyped) -> ActivityBoundary
20
26
  def self.current: (untyped, captured_at: untyped) -> ActivityBoundary
21
27
 
22
- # : (kind: Symbol, version_id: untyped, item_type: untyped, item_id: untyped, recorded_at: untyped) -> void
23
- def initialize: (kind: Symbol, version_id: untyped, item_type: untyped, item_id: untyped, recorded_at: untyped) -> void
28
+ # : (kind: Symbol, version_id: untyped, item_type: untyped, item_id: untyped, recorded_at: untyped, ?event: untyped, ?whodunnit: untyped) -> void
29
+ def initialize: (kind: Symbol, version_id: untyped, item_type: untyped, item_id: untyped, recorded_at: untyped, ?event: untyped, ?whodunnit: untyped) -> void
30
+
31
+ # : () -> bool
32
+ def version?: () -> bool
33
+
34
+ # : () -> bool
35
+ def current?: () -> bool
24
36
 
25
37
  # : () -> Hash[Symbol, untyped]
26
38
  def to_h: () -> Hash[Symbol, untyped]
@@ -37,6 +49,9 @@ module PaperTrailDiff
37
49
  # : (from_boundary: ActivityBoundary, to_boundary: ActivityBoundary, diff: Diff) -> void
38
50
  def initialize: (from_boundary: ActivityBoundary, to_boundary: ActivityBoundary, diff: Diff) -> void
39
51
 
52
+ # : () -> bool
53
+ def empty?: () -> bool
54
+
40
55
  # : () -> Hash[Symbol, untyped]
41
56
  def to_h: () -> Hash[Symbol, untyped]
42
57
  end
@@ -0,0 +1,58 @@
1
+ # Generated from lib/paper_trail_diff/association_diff_traversal.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Walks nested singular and collection association differences.
5
+ class AssociationDiffTraversal < TraversalEmitter
6
+ # : (^(TraversalEntry) -> void) -> void
7
+ def initialize: (^(TraversalEntry) -> void) -> void
8
+
9
+ # : (association_diffs, association_path: traversal_association_path, record_path: traversal_record_path) -> void
10
+ def call: (association_diffs, association_path: traversal_association_path, record_path: traversal_record_path) -> void
11
+
12
+ # : (Hash[String, ValueChange], association_path: traversal_association_path, record_path: traversal_record_path, association_kind: Symbol?) -> void
13
+ def attributes: (Hash[String, ValueChange], association_path: traversal_association_path, record_path: traversal_record_path, association_kind: Symbol?) -> void
14
+
15
+ private
16
+
17
+ @snapshots: SnapshotTraversal
18
+
19
+ # : (association_diff, traversal_association_path, traversal_record_path) -> void
20
+ def walk_association: (association_diff, traversal_association_path, traversal_record_path) -> void
21
+
22
+ # : (String, ValueChange, traversal_association_path, traversal_record_path, Symbol?) -> void
23
+ def emit_attribute: (String, ValueChange, traversal_association_path, traversal_record_path, Symbol?) -> void
24
+
25
+ # : (CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
26
+ def walk_collection: (CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
27
+
28
+ # : (Array[RecordSnapshot], Symbol, traversal_state, CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
29
+ def walk_memberships: (Array[RecordSnapshot], Symbol, traversal_state, CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
30
+
31
+ # : (RecordSnapshot, Symbol, traversal_state, CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
32
+ def walk_membership: (RecordSnapshot, Symbol, traversal_state, CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
33
+
34
+ # : (RecordSnapshot, Symbol, traversal_state, CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
35
+ def emit_membership: (RecordSnapshot, Symbol, traversal_state, CollectionAssociationDiff, traversal_association_path, traversal_record_path) -> void
36
+
37
+ # : (ToOneAssociationDiff, traversal_association_path, traversal_record_path) -> void
38
+ def walk_to_one: (ToOneAssociationDiff, traversal_association_path, traversal_record_path) -> void
39
+
40
+ # : (ValueChange, Symbol, traversal_association_path, traversal_record_path) -> void
41
+ def walk_relationship: (ValueChange, Symbol, traversal_association_path, traversal_record_path) -> void
42
+
43
+ # : (ValueChange, Symbol, traversal_association_path, traversal_record_path) -> void
44
+ def emit_relationship: (ValueChange, Symbol, traversal_association_path, traversal_record_path) -> void
45
+
46
+ # : (RecordSnapshot?, traversal_state, Symbol, traversal_association_path, traversal_record_path) -> void
47
+ def walk_related: (RecordSnapshot?, traversal_state, Symbol, traversal_association_path, traversal_record_path) -> void
48
+
49
+ # : (ValueChange) -> Symbol
50
+ def relationship_kind: (ValueChange) -> Symbol
51
+
52
+ # : (RecordChange, Symbol, traversal_association_path, traversal_record_path) -> void
53
+ def walk_record_change: (RecordChange, Symbol, traversal_association_path, traversal_record_path) -> void
54
+
55
+ # : (RecordChange, Symbol, traversal_association_path, traversal_record_path) -> void
56
+ def emit_record_change: (RecordChange, Symbol, traversal_association_path, traversal_record_path) -> void
57
+ end
58
+ end
@@ -0,0 +1,29 @@
1
+ # Generated from lib/paper_trail_diff/snapshot_traversal.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Walks nested state included in an added, removed, or replaced record snapshot.
5
+ class SnapshotTraversal < TraversalEmitter
6
+ # : (RecordSnapshot, association_path: traversal_association_path, record_path: traversal_record_path, state: traversal_state, ?association_kind: Symbol?, ?include_record: bool) -> void
7
+ def call: (RecordSnapshot, association_path: traversal_association_path, record_path: traversal_record_path, state: traversal_state, ?association_kind: Symbol?, ?include_record: bool) -> void
8
+
9
+ private
10
+
11
+ # : (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
12
+ def emit_record: (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
13
+
14
+ # : (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
15
+ def emit_attributes: (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
16
+
17
+ # : (String, untyped, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
18
+ def emit_attribute: (String, untyped, traversal_association_path, traversal_record_path, traversal_state, Symbol?) -> void
19
+
20
+ # : (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
21
+ def emit_associations: (RecordSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
22
+
23
+ # : (AssociationSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
24
+ def emit_association: (AssociationSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
25
+
26
+ # : (AssociationSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
27
+ def emit_association_records: (AssociationSnapshot, traversal_association_path, traversal_record_path, traversal_state) -> void
28
+ end
29
+ end
@@ -7,11 +7,18 @@ module PaperTrailDiff
7
7
 
8
8
  attr_reader to_version: untyped
9
9
 
10
+ attr_reader from_boundary: ActivityBoundary
11
+
12
+ attr_reader to_boundary: ActivityBoundary
13
+
10
14
  attr_reader diff: Diff
11
15
 
12
16
  # : (from_version: untyped, to_version: untyped, diff: Diff) -> void
13
17
  def initialize: (from_version: untyped, to_version: untyped, diff: Diff) -> void
14
18
 
19
+ # : () -> bool
20
+ def empty?: () -> bool
21
+
15
22
  # : () -> Hash[Symbol, untyped]
16
23
  def to_h: () -> Hash[Symbol, untyped]
17
24
  end
@@ -0,0 +1,41 @@
1
+ # Generated from lib/paper_trail_diff/traversal.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Coordinates root lifecycle, scalar, and association traversal.
5
+ class DiffTraversal < TraversalEmitter
6
+ # : (Diff, ^(TraversalEntry) -> void) -> void
7
+ def initialize: (Diff, ^(TraversalEntry) -> void) -> void
8
+
9
+ # : () -> void
10
+ def call: () -> void
11
+
12
+ private
13
+
14
+ @associations: AssociationDiffTraversal
15
+
16
+ @diff: Diff
17
+
18
+ @snapshots: SnapshotTraversal
19
+
20
+ # : () -> void
21
+ def walk_presence_change: () -> void
22
+
23
+ # : (RecordSnapshot?, traversal_state) -> void
24
+ def walk_presence_snapshot: (RecordSnapshot?, traversal_state) -> void
25
+ end
26
+
27
+ # The complete structured difference between two normalized endpoints.
28
+ class Diff
29
+ # Walks semantic changes and the nested state carried by added or removed records.
30
+ # @rbs () { (TraversalEntry) -> void } -> Diff
31
+ # | () -> Enumerator[TraversalEntry, Diff]
32
+ def each_entry: () { (TraversalEntry) -> void } -> Diff
33
+ | () -> Enumerator[TraversalEntry, Diff]
34
+
35
+ # Walks only semantic changes, excluding snapshot state included for context.
36
+ # @rbs () { (TraversalEntry) -> void } -> Diff
37
+ # | () -> Enumerator[TraversalEntry, Diff]
38
+ def each_change: () { (TraversalEntry) -> void } -> Diff
39
+ | () -> Enumerator[TraversalEntry, Diff]
40
+ end
41
+ end
@@ -0,0 +1,16 @@
1
+ # Generated from lib/paper_trail_diff/traversal_emitter.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Shared entry construction for internal traversal collaborators.
5
+ class TraversalEmitter
6
+ # : (^(TraversalEntry) -> void) -> void
7
+ def initialize: (^(TraversalEntry) -> void) -> void
8
+
9
+ private
10
+
11
+ @receiver: ^(TraversalEntry) -> void
12
+
13
+ # : (kind: Symbol, context: traversal_context, association_path: traversal_association_path, record_path: traversal_record_path, value: untyped, ?association_kind: Symbol?, ?state: traversal_state?, ?attribute: String?) -> void
14
+ def emit: (kind: Symbol, context: traversal_context, association_path: traversal_association_path, record_path: traversal_record_path, value: untyped, ?association_kind: Symbol?, ?state: traversal_state?, ?attribute: String?) -> void
15
+ end
16
+ end
@@ -0,0 +1,52 @@
1
+ # Generated from lib/paper_trail_diff/traversal_entry.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # One immutable location and value emitted while walking a Diff tree.
5
+ class TraversalEntry
6
+ CONTEXTS: untyped
7
+
8
+ STATES: untyped
9
+
10
+ attr_reader kind: Symbol
11
+
12
+ attr_reader context: traversal_context
13
+
14
+ attr_reader association_path: traversal_association_path
15
+
16
+ attr_reader record_path: traversal_record_path
17
+
18
+ attr_reader association_kind: Symbol?
19
+
20
+ attr_reader state: traversal_state?
21
+
22
+ attr_reader attribute: String?
23
+
24
+ attr_reader value: untyped
25
+
26
+ # : (kind: Symbol, context: traversal_context, ?association_path: traversal_association_path, ?record_path: traversal_record_path, ?association_kind: Symbol?, ?state: traversal_state?, ?attribute: String?, ?value: untyped) -> void
27
+ def initialize: (kind: Symbol, context: traversal_context, ?association_path: traversal_association_path, ?record_path: traversal_record_path, ?association_kind: Symbol?, ?state: traversal_state?, ?attribute: String?, ?value: untyped) -> void
28
+
29
+ # : () -> bool
30
+ def change?: () -> bool
31
+
32
+ # : () -> bool
33
+ def included_state?: () -> bool
34
+
35
+ # : () -> String?
36
+ def association: () -> String?
37
+
38
+ # : () -> RecordReference?
39
+ def record: () -> RecordReference?
40
+
41
+ # : () -> Hash[Symbol, untyped]
42
+ def to_h: () -> Hash[Symbol, untyped]
43
+
44
+ private
45
+
46
+ # : (Symbol, Symbol?) -> void
47
+ def validate!: (Symbol, Symbol?) -> void
48
+
49
+ # : (traversal_association_path) -> traversal_association_path
50
+ def immutable_names: (traversal_association_path) -> traversal_association_path
51
+ end
52
+ end
@@ -53,4 +53,12 @@ module PaperTrailDiff
53
53
  type ignore_option = Array[String | Symbol] | Hash[String | Symbol, untyped]
54
54
 
55
55
  type reference_key = :type | :id | "type" | "id"
56
+
57
+ type traversal_context = :change | :included_state
58
+
59
+ type traversal_state = :before | :after
60
+
61
+ type traversal_association_path = Array[String]
62
+
63
+ type traversal_record_path = Array[RecordReference]
56
64
  end