TypedEAV Documentation GitHub

Public API reference

This is an index of application-facing entry points. Linked guides explain examples, supported types, validation, and transaction boundaries. Internal query builders, dispatchers, caches, and callback methods are not extension APIs.

Host models and records

Declare has_typed_eav(scope_method: nil, parent_scope_method: nil, types: nil, versioned: false) on an Active Record model. Scope methods name record accessors; parent_scope_method requires scope_method. types: nil allows registered types; an array restricts them. Versioning additionally requires the global boot-time switch. Use the host’s polymorphic_name for entity_type.

Record method Contract
typed_values Active Record association; normal saves validate and persist values with the host.
typed_eav_definitions Visible definitions for this record’s partition, including same-name candidates.
typed_eav_scope, typed_eav_parent_scope Configured accessor values normalized to strings, or nil.
initialize_typed_values Build missing effective fields with defaults in memory; returns typed_values. Save separately.
typed_eav_value(name) Logical Ruby value, or nil when absent.
set_typed_eav_value(name, value) Stage a value by effective field name; unknown names are ignored. Save separately.
typed_eav_hash Hash of field names to logical values.
typed_eav_attributes= / typed_eav= Named entries such as [{name: "age", value: 30}]; supports _destroy.
typed_values_attributes= Rails nested attributes using field_id, optional Value id, value, and _destroy.
typed_eav_changes Pending logical changes as {name => [before, after]}.
saved_typed_eav_changes Logical changes from the latest successful host save; reload/rollback clears them.

See reading, writing, and forms, defaults, and scoping.

Host queries

These methods are available on the host class and through Active Record relations. The query methods below (including typed_eav_definitions) accept scope: and parent_scope:. Omitted keywords use ambient resolution; explicit nil selects the global axis. These select field definitions, not authorized host rows: start with an appropriately filtered host relation.

Method Result and defaults
where_typed_eav(*filters, include_missing: false) Active Record relation; filters use name, op (default :eq), and value.
with_field(name, operator_or_value = nil, value = nil, include_missing: false) Single-filter relation; two-argument non-Symbol value implies equality.
order_typed_eav(name, direction: :asc, nulls: :last) Relation ordered by a supported scalar field, then host primary key. Replaces prior ordering.
distinct_typed_eav_values(name, limit: 100) Array of distinct scalar values in database order.
count_distinct_typed_eav_values(name) Integer distinct count, including an explicit NULL category.
typed_eav_value_counts(name, limit: 100) Hash of scalar values to counts.
aggregate_typed_eav(name, operation:) :min, :max, or :sum for Integer/Decimal/Percentage; typed number or nil for empty min/max.
typed_eav_definitions Relation of visible field definitions; does not collapse names.

Missing rows differ from explicit NULL rows. include_missing: true broadens :is_null and is ignored by other operators. Scalar APIs reject unsupported field families and all-partition ambiguity with ArgumentError. See queries for operators, NULL behavior, limits, and errors.

Bulk operations

Host class method Result and defaults
typed_eav_hash_for(records, fields: nil, source: :database) {record.id => {field_name => value}}; optional selected field names; source: :preloaded reads loaded associations.
bulk_set_typed_eav_values(records, values_by_field_name, version_grouping: :default, transaction: :all, chunk_size: nil) Normal host saves; returns {successes: [...], errors_by_record: {record => errors_hash}}.
bulk_set_typed_eav_values_per_record(values_by_record, version_grouping: :default, transaction: :all, chunk_size: nil) Same result, with {record => {field_name => value}} input.
bulk_upsert_typed_eav_values(records, values_by_field_name, acknowledge_reduced_semantics: false, transaction: :all, chunk_size: nil) Written row count; requires explicit acknowledgement, skips persistence callbacks and audit versions.

Normal bulk writes collect validation failures per record; an unexpected exception can roll back the active transaction. transaction: :chunks requires a positive chunk_size; prior chunks remain committed on later failure. See bulk operations before choosing either write path.

Field definitions and values

Use TypedEAV::Field::<Type>.create! and ordinary Active Record updates for field metadata; field_options holds Select/MultiSelect choices. The fields guide covers every built-in type and its options.

API Purpose
field.default_value / default_value= Read/set the logical default. Explicit value assignment can override it with nil.
field.backfill_default!(relation: nil) Synchronously apply a configured default to eligible existing hosts in batches; no count/result contract.
field.destroy! Apply the field’s field_dependent policy.
field.destroy_with_values_in_batches!(batch_size: 1_000) Resumable deletion for persisted field_dependent: :destroy fields; requires no open transaction.
field.move_higher, move_lower, move_to_top, move_to_bottom, insert_at(position) Reorder within the field’s partition.
field.field_type_name, display_name, array_field?, optionable?, allowed_option_values Metadata for rendering and field-management interfaces.
field.cast(raw) Custom-type protocol returning [cast_value, invalid]; casting alone does not establish validity.
value.value / value= Read/write the field’s logical value, including multi-cell types.
value.history Versions ordered newest first by timestamp and ID.
value.revert_to(version) Save the version’s before state and write a new version; rejects another Value’s version, create versions, and destroyed source Values.

See default initialization and backfill, field deletion, and custom types for their contracts. Full history after Value deletion requires querying TypedEAV::ValueVersion by entity and field identity; see events and versioning.

Schema and CSV

API Result
TypedEAV::SchemaPortability.export_schema(entity_type:, scope: nil, parent_scope: nil) String-keyed versioned schema Hash for an exact partition, including fields and sections; excludes values.
TypedEAV::SchemaPortability.preview_schema(hash, on_conflict: :error) Read-only JSON-safe comparison and predicted actions; advisory, not a reservation or validation guarantee.
TypedEAV::SchemaPortability.import_schema(hash, on_conflict: :error) Counts under "created", "updated", "skipped", "unchanged", plus "errors"; import runs in a transaction and failures can raise.
TypedEAV::SchemaPortability.export_snapshot_schema(entity_type:, scope: nil, parent_scope: nil) Lean versioned field projection; not a full import payload or a value backup.
TypedEAV::CSVMapper.row_to_attributes(row, mapping, fields_by_name: nil) Result with frozen attributes/errors Hashes and success?/failure?. Does not save records.

Field::Base.export_schema and .import_schema remain compatible delegators. Conflict policies are :error, :skip, and :overwrite; type swaps are refused. CSV mapping uses uniformly String header keys or Integer index keys, with field names as values. Typed mode casts via supplied definitions, reports cast errors, and skips unknown fields. Normal model validation must still run. See schema portability and CSV imports.

Partition helpers

TypedEAV::Partition expects explicitly resolved scope values; it does not consult ambient scope. Visibility methods accept scope: nil, parent_scope: nil, and mode: :partition. Use mode: :all_partitions only for an authorized admin bypass. Invalid modes and orphan parent scopes raise ArgumentError in partition mode.

Method Result
visible_fields(entity_type: nil, ...) Field relation, including global, scope-only, and full-tuple candidates.
effective_fields_by_name(entity_type:, ...) {name => field} with most-specific precedence; all-partitions mode instead returns {name => [fields]}.
definitions_by_name(defs) Collapse supplied definitions by name, most-specific winning. Supply only the intended visible set.
definitions_multimap_by_name(defs) Group supplied definitions as {name => [fields]} without collapsing.
visible_sections(entity_type:, ...) Relation of sections visible to the tuple.
find_visible_section!(id, entity_type:, ...) Visible Section, or ActiveRecord::RecordNotFound.

These helpers constrain definition visibility; application authorization still belongs to the caller. See scoping.