Class: PaperTrailDiff::ComparisonBatch
- Inherits:
-
Object
- Object
- PaperTrailDiff::ComparisonBatch
- Defined in:
- lib/paper_trail_diff/comparison_batch.rb,
sig/generated/paper_trail_diff/comparison_batch.rbs
Overview
Validates and executes independent comparisons with shared live endpoint loading.
Instance Method Summary collapse
-
#call ⇒ comparison_results
: () -> comparison_results.
-
#compare(from, to, live_snapshots) ⇒ Diff
: (untyped, untyped, Hash[identity, RecordSnapshot]) -> Diff.
-
#comparison_pair(comparison, index) ⇒ [ untyped, untyped ]
: (untyped, Integer) -> [untyped, untyped].
-
#comparison_pairs ⇒ Array[[ untyped, untyped ]]
: () -> Array[[untyped, untyped]].
-
#endpoint(comparison, name) ⇒ Object
: (Hash[untyped, untyped], Symbol) -> untyped.
-
#endpoint_requirements(pairs) ⇒ Hash[untyped, bool]
: (Array[[untyped, untyped]]) -> Hash[untyped, bool].
-
#ensure_unique_identities!(pairs) ⇒ void
: (Array[[untyped, untyped]]) -> void.
-
#entry_identity(from, to) ⇒ identity
: (untyped, untyped) -> identity.
-
#historical_versions(pairs, live_records) ⇒ Array[untyped]
: (Array[[untyped, untyped]], Hash[identity, untyped]) -> Array.
-
#initialize(comparisons, live_loader:, preparer:, history_preparer:, historical_snapshotter:, live_normalizer:) ⇒ ComparisonBatch
constructor
: (Array, live_loader: untyped, preparer: untyped, history_preparer: untyped, historical_snapshotter: untyped, live_normalizer: untyped) -> void.
-
#load_live_records(endpoints) ⇒ Hash[identity, untyped]
: (Array) -> Hash[identity, untyped].
-
#normalize_live_records(records) ⇒ Hash[identity, RecordSnapshot]
: (Hash[identity, untyped]) -> Hash[identity, RecordSnapshot].
-
#prepare_endpoint_classes!(pairs) ⇒ void
: (Array[[untyped, untyped]]) -> void.
-
#prepare_historical_batches!(pairs, live_records) ⇒ void
: (Array[[untyped, untyped]], Hash[identity, untyped]) -> void.
-
#prepared_live_snapshots(pairs) ⇒ Hash[identity, RecordSnapshot]
: (Array[[untyped, untyped]]) -> Hash[identity, RecordSnapshot].
-
#results(resolved, live_snapshots) ⇒ comparison_results
A boundary symbol that stayed unresolved means the root has no recorded history.
-
#snapshot(endpoint, live_snapshots) ⇒ RecordSnapshot?
: (untyped, Hash[identity, RecordSnapshot]) -> RecordSnapshot?.
-
#symbolic?(endpoint) ⇒ Boolean
: (untyped) -> bool.
-
#valid_comparison!(comparison, index) ⇒ void
: (untyped, Integer) -> void.
Constructor Details
#initialize(comparisons, live_loader:, preparer:, history_preparer:, historical_snapshotter:, live_normalizer:) ⇒ ComparisonBatch
: (Array, live_loader: untyped, preparer: untyped, history_preparer: untyped, historical_snapshotter: untyped, live_normalizer: untyped) -> void
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 8 def initialize( # rubocop:disable Metrics/ParameterLists comparisons, live_loader:, preparer:, history_preparer:, historical_snapshotter:, live_normalizer: ) @comparisons = comparisons @live_loader = live_loader @preparer = preparer @history_preparer = history_preparer @historical_snapshotter = historical_snapshotter @live_normalizer = live_normalizer end |
Instance Method Details
#call ⇒ comparison_results
: () -> comparison_results
25 26 27 28 29 30 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 25 def call resolved = BatchBoundaryResolver.new(comparison_pairs).call pairs = resolved.reject { |pair| pair.any? { |endpoint| symbolic?(endpoint) } } ensure_unique_identities!(resolved) results(resolved, prepared_live_snapshots(pairs)).freeze end |
#compare(from, to, live_snapshots) ⇒ Diff
: (untyped, untyped, Hash[identity, RecordSnapshot]) -> Diff
74 75 76 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 74 def compare(from, to, live_snapshots) Engine.compare(snapshot(from, live_snapshots), snapshot(to, live_snapshots)) end |
#comparison_pair(comparison, index) ⇒ [ untyped, untyped ]
: (untyped, Integer) -> [untyped, untyped]
129 130 131 132 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 129 def comparison_pair(comparison, index) valid_comparison!(comparison, index) [endpoint(comparison, :from), endpoint(comparison, :to)] end |
#comparison_pairs ⇒ Array[[ untyped, untyped ]]
: () -> Array[[untyped, untyped]]
118 119 120 121 122 123 124 125 126 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 118 def comparison_pairs unless @comparisons.is_a?(Array) raise ConfigurationError, 'comparisons: must be an array of from:/to: hashes' end @comparisons.map.with_index do |comparison, index| comparison_pair(comparison, index) end end |
#endpoint(comparison, name) ⇒ Object
: (Hash[untyped, untyped], Symbol) -> untyped
146 147 148 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 146 def endpoint(comparison, name) comparison.key?(name) ? comparison.fetch(name) : comparison.fetch(name.to_s) end |
#endpoint_requirements(pairs) ⇒ Hash[untyped, bool]
: (Array[[untyped, untyped]]) -> Hash[untyped, bool]
166 167 168 169 170 171 172 173 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 166 def endpoint_requirements(pairs) requirements = {} #: Hash[untyped, bool] pairs.flatten.each_with_object(requirements) do |endpoint, collected| historical = Endpoint.version?(endpoint) model_class = historical ? Endpoint.model_class(endpoint) : endpoint.class collected[model_class] = collected.fetch(model_class, false) || historical end end |
#ensure_unique_identities!(pairs) ⇒ void
This method returns an undefined value.
: (Array[[untyped, untyped]]) -> void
151 152 153 154 155 156 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 151 def ensure_unique_identities!(pairs) identities = pairs.map { |from, to| entry_identity(from, to) } return if identities.uniq.length == identities.length raise ConfigurationError, 'comparisons: root identities must be unique' end |
#entry_identity(from, to) ⇒ identity
: (untyped, untyped) -> identity
69 70 71 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 69 def entry_identity(from, to) Endpoint.identity(symbolic?(from) ? to : from) end |
#historical_versions(pairs, live_records) ⇒ Array[untyped]
: (Array[[untyped, untyped]], Hash[identity, untyped]) -> Array
110 111 112 113 114 115 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 110 def historical_versions(pairs, live_records) selected = pairs.flatten.select do |endpoint| Endpoint.version?(endpoint) && live_records.key?(Endpoint.identity(endpoint)) end selected.uniq { |version| [version.class.name, version.id] } end |
#load_live_records(endpoints) ⇒ Hash[identity, untyped]
: (Array) -> Hash[identity, untyped]
86 87 88 89 90 91 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 86 def load_live_records(endpoints) records = endpoints.reject { |endpoint| Endpoint.version?(endpoint) }.uniq do |record| Endpoint.identity(record) end @live_loader.call(records) end |
#normalize_live_records(records) ⇒ Hash[identity, RecordSnapshot]
: (Hash[identity, untyped]) -> Hash[identity, RecordSnapshot]
94 95 96 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 94 def normalize_live_records(records) records.transform_values { |record| @live_normalizer.call(record) } end |
#prepare_endpoint_classes!(pairs) ⇒ void
This method returns an undefined value.
: (Array[[untyped, untyped]]) -> void
159 160 161 162 163 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 159 def prepare_endpoint_classes!(pairs) endpoint_requirements(pairs).each do |model_class, historical| @preparer.call(model_class, historical: historical) end end |
#prepare_historical_batches!(pairs, live_records) ⇒ void
This method returns an undefined value.
: (Array[[untyped, untyped]], Hash[identity, untyped]) -> void
99 100 101 102 103 104 105 106 107 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 99 def prepare_historical_batches!(pairs, live_records) grouped = historical_versions(pairs, live_records).group_by do |version| Endpoint.model_class(version) end grouped.each_value do |versions| records = versions.map { |version| live_records.fetch(Endpoint.identity(version)) }.uniq @history_preparer.call(records, versions) end end |
#prepared_live_snapshots(pairs) ⇒ Hash[identity, RecordSnapshot]
: (Array[[untyped, untyped]]) -> Hash[identity, RecordSnapshot]
42 43 44 45 46 47 48 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 42 def prepared_live_snapshots(pairs) pairs.each { |from, to| Endpoint.validate_pair!(from, to) } prepare_endpoint_classes!(pairs) live_records = load_live_records(pairs.flatten) prepare_historical_batches!(pairs, live_records) normalize_live_records(live_records) end |
#results(resolved, live_snapshots) ⇒ comparison_results
A boundary symbol that stayed unresolved means the root has no recorded history. An absent history is an empty result rather than a failed request, matching how the timeline APIs answer the same question. : (Array[[untyped, untyped]], Hash[identity, RecordSnapshot]) -> comparison_results
59 60 61 62 63 64 65 66 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 59 def results(resolved, live_snapshots) resolved.to_h do |from, to| identity = Support.immutable_copy(entry_identity(from, to)) next [identity, Diff.new] if symbolic?(from) || symbolic?(to) [identity, compare(from, to, live_snapshots)] end end |
#snapshot(endpoint, live_snapshots) ⇒ RecordSnapshot?
: (untyped, Hash[identity, RecordSnapshot]) -> RecordSnapshot?
79 80 81 82 83 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 79 def snapshot(endpoint, live_snapshots) return @historical_snapshotter.call(endpoint) if Endpoint.version?(endpoint) live_snapshots.fetch(Endpoint.identity(endpoint)) end |
#symbolic?(endpoint) ⇒ Boolean
: (untyped) -> bool
51 52 53 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 51 def symbolic?(endpoint) BatchBoundaryResolver.symbolic?(endpoint) end |
#valid_comparison!(comparison, index) ⇒ void
This method returns an undefined value.
: (untyped, Integer) -> void
135 136 137 138 139 140 141 142 143 |
# File 'lib/paper_trail_diff/comparison_batch.rb', line 135 def valid_comparison!(comparison, index) if comparison.is_a?(Hash) keys = comparison.keys.map(&:to_s) return if keys.sort == %w[from to] && keys.length == 2 end = "comparisons[#{index}]: must contain exactly from: and to:" raise ConfigurationError, end |