Class: TypedEAV::BulkRead

Inherits:
Object
  • Object
show all
Defined in:
lib/typed_eav/bulk_read.rb

Overview

Bulk-read query object. Returns { record_id => { field_name => value } } for an Enumerable of host records — the class-method bulk variant of HasTypedEAV::InstanceMethods#typed_eav_hash. N+1-free regardless of record count or field count.

fields: is an optional projection of field names. A nil selection keeps the all-fields behavior; a non-nil selection is normalized to unique strings, and only the selected winning definitions' values are loaded. Unknown names are ignored, as are names that are not defined for a particular record's partition tuple. An empty selection returns one empty inner hash per record without querying definitions or values.

source: :database (the default) always reads a fresh Value graph. The explicit source: :preloaded mode projects only the already-loaded typed_values targets and their loaded field associations; it never falls back to an association query. Incomplete preload requirements raise ArgumentError before projection. The preloaded mode is therefore a snapshot of caller-owned in-memory records and can include unsaved Value assignments; it never saves or mutates those records.

Pipeline

1. validate_records!    

Query bound

Database mode performs up to three SELECTs — one bulk Value query, one field-association query for those values, and one definition query for the union of requested partitions. The preloaded mode performs one fresh definition SELECT and reads Value/field association targets in memory; fields: [] bypasses even that definition query. Both bounds are independent of record count and partition cardinality.

Single-class invariant

The polymorphic value query targets the host's canonical Rails polymorphic_name, so an STI subclass reads rows stored for its base class. Mixed, unrelated input would still be invalid; STI subclasses pass via records.all?(host_class).

Instance Method Summary collapse

Constructor Details

#initialize(host_class:, records:, fields: nil, source: :database) ⇒ BulkRead

Returns a new instance of BulkRead.



53
54
55
56
57
58
# File 'lib/typed_eav/bulk_read.rb', line 53

def initialize(host_class:, records:, fields: nil, source: :database)
  @host_class = host_class
  @records    = records
  @fields     = fields
  @source     = source
end

Instance Method Details

#to_hashObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/typed_eav/bulk_read.rb', line 60

def to_hash
  validate_source!

  records = coerce_records
  return {} if records.empty?

  validate_record_classes!(records)

  selected_names = normalize_fields
  return empty_results(records) if selected_names == []

  tuples_by_record = group_by_tuple(records)
  winning_ids_by_tuple = winning_ids_by_tuple(tuples_by_record.values.uniq, selected_names)
  values_by_record_id = if @source == :preloaded
                          preloaded_values(records, tuples_by_record, winning_ids_by_tuple, selected_names)
                        else
                          preload_values(records, winning_ids_by_tuple, selected_names)
                        end

  build_result(records, tuples_by_record, winning_ids_by_tuple, values_by_record_id, selected_names)
end