Class: PaperTrailDiff::AnalysisBatch

Inherits:
Object
  • Object
show all
Defined in:
lib/paper_trail_diff/analysis_batch.rb,
sig/generated/paper_trail_diff/analysis_batch.rbs

Overview

Builds one Analysis per root over a shared range, selecting every root's versions and preparing their association history once for the whole batch rather than once per root.

Instance Method Summary collapse

Constructor Details

#initialize(records, time_range:, live_loader:, history_preparer:, analyzer:, version_scope: nil, close_on_current: false) ⇒ AnalysisBatch

: (Array, time_range: TimeRange?, live_loader: untyped, history_preparer: untyped, analyzer: untyped, ?version_scope: untyped, ?close_on_current: bool) -> void

Parameters:

  • (Array[untyped])
  • time_range: (TimeRange, nil)
  • live_loader: (Object)
  • history_preparer: (Object)
  • analyzer: (Object)
  • version_scope: (Object) (defaults to: nil)
  • close_on_current: (Boolean) (defaults to: false)


10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/paper_trail_diff/analysis_batch.rb', line 10

def initialize( # rubocop:disable Metrics/ParameterLists
  records, time_range:, live_loader:, history_preparer:, analyzer:, version_scope: nil,
  close_on_current: false
)
  @records = records
  @time_range = time_range
  @version_scope = validated_scope(version_scope)
  @close_on_current = close_on_current
  @live_loader = live_loader
  @history_preparer = history_preparer
  @analyzer = analyzer
end

Instance Method Details

#analysis_for(record, plan) ⇒ Analysis

A root with no versions in range has nothing to report, which is an empty result rather than a failed request. : (untyped, RootVersionPlan) -> Analysis

Parameters:

Returns:



90
91
92
93
94
# File 'lib/paper_trail_diff/analysis_batch.rb', line 90

def analysis_for(record, plan)
  return Analysis.empty if plan.empty?

  @analyzer.call(record, plan)
end

#callHash[identity, Analysis]

: () -> Hash[identity, Analysis]

Returns:



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/paper_trail_diff/analysis_batch.rb', line 24

def call
  records = validated_records
  loaded = @live_loader.call(records)
  selected = BatchedRootVersions.new(
    records, time_range: @time_range, version_scope: @version_scope,
             live_endpoints: (loaded if @close_on_current)
  ).call
  prepare(records, selected, loaded)
  records.to_h do |record|
    key = Endpoint.identity(record)
    plan = selected.fetch(key, RootVersionPlan.empty)
    [Support.immutable_copy(key), analysis_for(record, plan)]
  end.freeze
end

#prepare(records, selected, loaded) ⇒ void

This method returns an undefined value.

Association history is prepared per model class across every selected root version, which is the work that would otherwise repeat for each record. The roots are preloaded first, because preparation reads their current association state as a fallback and would otherwise walk it one root at a time. : (Array, Hash[Array[String], RootVersionPlan], Hash[Array[String], untyped]) -> void

Parameters:

  • (Array[untyped])
  • (Hash[Array[String], RootVersionPlan])
  • (Hash[Array[String], untyped])


75
76
77
78
79
80
81
82
83
84
85
# File 'lib/paper_trail_diff/analysis_batch.rb', line 75

def prepare(records, selected, loaded)
  records.group_by(&:class).each_value do |grouped|
    versions = grouped.flat_map do |record|
      selected.fetch(Endpoint.identity(record), RootVersionPlan.empty).versions
    end
    next if versions.empty?

    roots = grouped.map { |record| loaded.fetch(Endpoint.identity(record), record) }
    @history_preparer.call(roots, versions)
  end
end

#validated_recordsArray[untyped]

: () -> Array

Returns:

  • (Array[untyped])


59
60
61
62
63
64
65
66
67
# File 'lib/paper_trail_diff/analysis_batch.rb', line 59

def validated_records
  raise ConfigurationError, 'records: must be an array' unless @records.is_a?(Array)

  @records.each { |record| Endpoint.validate!(record) }
  identities = @records.map { |record| Endpoint.identity(record) }
  return @records if identities.uniq.length == identities.length

  raise ConfigurationError, 'records: identities must be unique'
end

#validated_scope(scope) ⇒ Object

A filter is a callable that narrows the version relation, so it is checked up front rather than failing partway through a batch. : (untyped) -> untyped

Parameters:

  • (Object)

Returns:

  • (Object)


52
53
54
55
56
# File 'lib/paper_trail_diff/analysis_batch.rb', line 52

def validated_scope(scope)
  return scope if scope.nil? || scope.respond_to?(:call)

  raise ConfigurationError, 'version_scope: must respond to call'
end