Class: PaperTrailDiff::PreparedRecordSeries
- Inherits:
-
Object
- Object
- PaperTrailDiff::PreparedRecordSeries
- Defined in:
- lib/paper_trail_diff/prepared_record_index.rb,
sig/generated/paper_trail_diff/prepared_record_index.rbs
Overview
Versions and live fallback for one model identity.
Instance Attribute Summary collapse
- #versions ⇒ Array[untyped] readonly
Instance Method Summary collapse
-
#boundary_index(boundary) ⇒ Integer?
A version is eligible when it is at or after the boundary, or shares the boundary's transaction.
-
#build_transaction_positions ⇒ Hash[untyped, Integer]
: () -> Hash[untyped, Integer].
-
#initialize(versions:, live:, state_loader: PreparedVersionStateLoader.new) ⇒ PreparedRecordSeries
constructor
: (versions: Array, live: PreparedRecordState?, ?state_loader: PreparedVersionStateLoader) -> void.
-
#record_before(boundary) ⇒ Object
: (untyped) -> untyped.
-
#records ⇒ Array[untyped]
: () -> Array.
-
#state_after(index) ⇒ PreparedRecordState?
: (Integer) -> PreparedRecordState?.
-
#state_for(version) ⇒ PreparedRecordState?
: (untyped) -> PreparedRecordState?.
-
#transaction_index(boundary) ⇒ Integer?
: (untyped) -> Integer?.
-
#transition(version) ⇒ [ Hash[untyped, untyped], Hash[untyped, untyped] ]?
: (untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?.
Constructor Details
#initialize(versions:, live:, state_loader: PreparedVersionStateLoader.new) ⇒ PreparedRecordSeries
: (versions: Array, live: PreparedRecordState?, ?state_loader: PreparedVersionStateLoader) -> void
111 112 113 114 115 116 117 118 119 120 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 111 def initialize(versions:, live:, state_loader: PreparedVersionStateLoader.new) @versions = Support.chronological_sort(versions).freeze @version_positions = @versions.each_with_index.to_h do |version, index| [version.id.to_s, index] end.freeze @transaction_positions = build_transaction_positions @live = live @state_loader = state_loader @states = {} #: Hash[untyped, PreparedRecordState?] end |
Instance Attribute Details
#versions ⇒ Array[untyped] (readonly)
108 109 110 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 108 def versions @versions end |
Instance Method Details
#boundary_index(boundary) ⇒ Integer?
A version is eligible when it is at or after the boundary, or shares the boundary's transaction. The first is monotonic over the chronological list and the second is indexed, so neither rescans a long history once per boundary. : (untyped) -> Integer?
168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 168 def boundary_index(boundary) created_at = boundary.created_at chronological = versions.bsearch_index do |candidate| candidate.created_at >= created_at end transactional = transaction_index(boundary) return chronological unless transactional return transactional unless chronological [chronological, transactional].min end |
#build_transaction_positions ⇒ Hash[untyped, Integer]
: () -> Hash[untyped, Integer]
189 190 191 192 193 194 195 196 197 198 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 189 def build_transaction_positions positions = {} #: Hash[untyped, Integer] @versions.each_with_index do |version, index| next unless version.respond_to?(:transaction_id) transaction_id = version.transaction_id positions[transaction_id] ||= index if transaction_id end positions.freeze end |
#record_before(boundary) ⇒ Object
: (untyped) -> untyped
123 124 125 126 127 128 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 123 def record_before(boundary) index = boundary_index(boundary) return state_for(versions.fetch(index))&.instantiate if index @live&.instantiate end |
#records ⇒ Array[untyped]
: () -> Array
131 132 133 134 135 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 131 def records version_records = versions.filter_map { |version| state_for(version)&.instantiate } live = @live live ? [*version_records, live.instantiate] : version_records end |
#state_after(index) ⇒ PreparedRecordState?
: (Integer) -> PreparedRecordState?
158 159 160 161 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 158 def state_after(index) successor = versions[index + 1] successor ? state_for(successor) : @live end |
#state_for(version) ⇒ PreparedRecordState?
: (untyped) -> PreparedRecordState?
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 201 def state_for(version) return @states[version.id] if @states.key?(version.id) prepared = @state_loader.call(version) return @states[version.id] = prepared if prepared record = version.reify( dup: true, has_many: false, has_one: false, belongs_to: false, has_and_belongs_to_many: false ) @states[version.id] = record && PreparedRecordState.new(record) end |
#transaction_index(boundary) ⇒ Integer?
: (untyped) -> Integer?
181 182 183 184 185 186 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 181 def transaction_index(boundary) transaction_id = boundary.transaction_id if boundary.respond_to?(:transaction_id) return unless transaction_id @transaction_positions[transaction_id] end |
#transition(version) ⇒ [ Hash[untyped, untyped], Hash[untyped, untyped] ]?
: (untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?
138 139 140 141 142 143 144 145 146 147 |
# File 'lib/paper_trail_diff/prepared_record_index.rb', line 138 def transition(version) index = @version_positions[version.id.to_s] return unless index before = state_for(versions.fetch(index)) after = state_after(index) return unless before && after && before.model_class == after.model_class [before.attributes, after.attributes] end |