Module: TypedEAV::SchemaPortability
- Defined in:
- lib/typed_eav/schema_portability.rb
Overview
Export and import field + section definitions for an exact partition tuple. Value rows are intentionally out of scope.
Class Method Summary collapse
- .export_schema(entity_type:, scope: nil, parent_scope: nil) ⇒ Object
-
.export_snapshot_schema(entity_type:, scope: nil, parent_scope: nil) ⇒ Hash
Lean, restore-oriented projection of the field schema for a partition tuple.
- .import_schema(hash, on_conflict: :error) ⇒ Object
Class Method Details
.export_schema(entity_type:, scope: nil, parent_scope: nil) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/typed_eav/schema_portability.rb', line 8 def export_schema(entity_type:, scope: nil, parent_scope: nil) fields = TypedEAV::Field::Base .where(entity_type: entity_type, scope: scope, parent_scope: parent_scope) .includes(:field_options) .order(:sort_order) .map { |field| export_field_entry(field) } sections = TypedEAV::Section .where(entity_type: entity_type, scope: scope, parent_scope: parent_scope) .order(:sort_order) .map { |section| export_section_entry(section) } { "schema_version" => 1, "entity_type" => entity_type, "scope" => scope, "parent_scope" => parent_scope, "fields" => fields, "sections" => sections, } end |
.export_snapshot_schema(entity_type:, scope: nil, parent_scope: nil) ⇒ Hash
Lean, restore-oriented projection of the field schema for a partition tuple. Sibling to export_schema — same partition filter, narrower per-field surface, no sections, no partition-identity keys.
The envelope is:
{
"snapshot_schema_version" => 1,
"fields" => [ <snapshot_field_entry>, ... ] # ordered by sort_order
}
The ‘snapshot_schema_version` integer will be bumped explicitly when the inner per-field shape evolves in a non-additive way — it is NOT frozen forever. Consumers should branch on the version to handle cross-version snapshots.
Each per-field entry is a strict subset of the full export_field_entry shape:
{
"name" => field.name,
"field_type_name" => field.field_type_name,
"required" => field.required,
"sort_order" => field.sort_order,
"options" => field.options,
"options_data" => [...] # ONLY present when field.optionable?
}
Omitted vs the full schema export: ‘entity_type`, `scope`, `parent_scope`, `type` (the AR STI class name), `field_dependent`, and `default_value_meta`. Non-optionable fields omit `options_data` entirely (absent, not nil, not an empty array).
The ‘field_type_name` value is the documented field-type dispatch identifier — robust to namespace relocations of the field class because it strips the namespace via `demodulize` before `underscore`-ing. It is NOT robust to renames of the leaf class itself: `Field::Select` → `“select”`, but renaming the class to `Field::Status` would change the dispatch identifier to `“status”`.
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/typed_eav/schema_portability.rb', line 74 def export_snapshot_schema(entity_type:, scope: nil, parent_scope: nil) fields = TypedEAV::Field::Base .where(entity_type: entity_type, scope: scope, parent_scope: parent_scope) .includes(:field_options) .order(:sort_order) .map { |field| export_snapshot_field_entry(field) } { "snapshot_schema_version" => 1, "fields" => fields, } end |
.import_schema(hash, on_conflict: :error) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/typed_eav/schema_portability.rb', line 87 def import_schema(hash, on_conflict: :error) validate_schema_version!(hash) validate_conflict_policy!(on_conflict) result = { "created" => 0, "updated" => 0, "skipped" => 0, "unchanged" => 0, "errors" => [] } TypedEAV::Field::Base.transaction do Array(hash["fields"]).each do |entry| import_field_entry(entry, on_conflict, result) end Array(hash["sections"]).each do |entry| import_section_entry(entry, on_conflict, result) end end result end |