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.

## Pipeline (one query per unique partition tuple + one bulk value preload)

1. validate_records!    — nil -> ArgumentError; single-class invariant
2. group_by_tuple       — `[typed_eav_scope, typed_eav_parent_scope]`
3. winning_ids_by_tuple — `typed_eav_definitions` per unique tuple via
                          `Partition.definitions_by_name` (shared
                          collision-precedence helper)
4. preload_values       — single SELECT across ALL records
5. build_result_hash    — per-record inner hash; orphan-skip + winning-id
                          precedence mirrored from the instance path.

## Query bound

- 1 SELECT typed_eav_values WHERE entity_type=? AND entity_id IN (?)
- 1 SELECT typed_eav_fields WHERE id IN (?)           (via includes)
- 1 SELECT typed_eav_fields per unique partition tuple

Total: 2 + (unique partition tuples) queries — independent of record count.

## Single-class invariant

The polymorphic value query (‘entity_type: host_class.name`) targets ONE class; mixed-class input would silently miss rows of the other class. STI subclasses pass via `records.all?(host_class)`.

Instance Method Summary collapse

Constructor Details

#initialize(host_class:, records:) ⇒ BulkRead

Returns a new instance of BulkRead.



34
35
36
37
# File 'lib/typed_eav/bulk_read.rb', line 34

def initialize(host_class:, records:)
  @host_class = host_class
  @records    = records
end

Instance Method Details

#to_hashObject



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/typed_eav/bulk_read.rb', line 39

def to_hash
  records = coerce_records
  return {} if records.empty?

  validate_record_classes!(records)

  tuples_by_record = group_by_tuple(records)
  winning_ids_by_tuple = winning_ids_by_tuple(tuples_by_record.values.uniq)
  values_by_record_id = preload_values(records)

  build_result(records, tuples_by_record, winning_ids_by_tuple, values_by_record_id)
end