Class: TypedEAV::ValueVersion
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- TypedEAV::ValueVersion
- Defined in:
- app/models/typed_eav/value_version.rb
Overview
Append-only audit log row for a TypedEAV::Value mutation. One row per :create / :update / :destroy event when the host entity opted into versioning AND the gem-level master switch is on. Written by TypedEAV::Versioning::Subscriber (plan 04-02), read via Value#history (plan 04-03) or directly via this model.
## Schema invariants (locked at 04-CONTEXT.md)
-
‘before_value` and `after_value` are jsonb hashes keyed by typed- column name (e.g., 42). Empty {} means “no recorded value” (typical of a :create event’s before, or a :destroy event’s after). null means “recorded nil” (a deliberate clear). The two are NOT semantically equivalent.
-
‘change_type` is one of “create” | “update” | “destroy” — string, not enum, for forward compat. Phase 04 ships these three; future phases may extend the validator.
-
‘value_id` and `field_id` are nullable: ON DELETE SET NULL on both FKs preserves the audit log when the live Value/Field is destroyed (matches Phase 02’s cascade pattern for typed_eav_values.field_id).
-
‘(entity_type, entity_id)` is the durable identity. Even after the Value row is destroyed and value_id is NULLed, the entity tuple tells consumers which host record this version belonged to.
-
‘changed_by` is a plain string — Lead’s plan-time decision (see 04-01-PLAN §Plan-time decisions §1). Apps resolve to AR records on the read side: ‘User.find_by(id: version.changed_by)`.
## Why no default_scope
Append-only logs benefit from explicit ordering at the call site (‘Value#history.order(changed_at: :desc)`) rather than a hidden default_scope that consumers must learn to override. Mirrors the gem’s existing convention (no default_scope on Value, Field::Base, Section, Option). The idx_te_vvs_value covering index serves the ‘(value_id, changed_at DESC)` query path natively.
Constant Summary collapse
- CHANGE_TYPES =
change_type closed set. Mirrors the Phase 02 field_dependent validator pattern (field/base.rb:56-59) — string column + inclusion validator narrows the set at the model layer while keeping schema migrations additive.
%w[create update destroy].freeze