typed_eav 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -2
- data/README.md +79 -1710
- data/RELEASING.md +81 -0
- data/docs/adr/0001-collapse-column-mapping-stack.md +28 -0
- data/docs/adr/0002-entity-query-orchestration.md +33 -0
- data/docs/adr/0003-keep-event-dispatcher-broker.md +41 -0
- data/docs/adr/0004-field-family-intermediate-bases.md +49 -0
- data/docs/adr/0005-keep-phase-six-modules-independent.md +48 -0
- data/docs/adr/0006-include-missing-via-set-complement.md +77 -0
- data/docs/adr/0007-visibility-versus-mutation-relations.md +33 -0
- data/docs/adr/0008-partial-covering-scalar-indexes.md +83 -0
- data/docs/adr/0009-string-search-indexing.md +110 -0
- data/docs/adr/0010-planner-statistics-policy.md +109 -0
- data/docs/adr/0011-multi-filter-query-strategy.md +111 -0
- data/docs/adr/0012-cross-scope-administrative-query-policy.md +76 -0
- data/docs/adr/0013-durable-versioning-and-field-deletion.md +125 -0
- data/docs/adr/index.md +101 -0
- data/docs/getting-started.md +79 -0
- data/docs/guides/architecture.md +125 -0
- data/docs/guides/bulk-operations.md +205 -0
- data/docs/guides/csv-import.md +88 -0
- data/docs/guides/development.md +73 -0
- data/docs/guides/events-and-versioning.md +360 -0
- data/docs/guides/fields.md +342 -0
- data/docs/guides/performance.md +107 -0
- data/docs/guides/queries.md +188 -0
- data/docs/guides/schema.md +134 -0
- data/docs/guides/scoping.md +254 -0
- data/docs/guides/upgrading.md +26 -0
- data/docs/guides/usage.md +259 -0
- data/docs/index.md +44 -0
- data/docs/maintaining.md +82 -0
- data/docs/reference/api.md +133 -0
- data/docs/reference/configuration.md +64 -0
- data/docs/reference/index.md +16 -0
- data/lib/typed_eav/version.rb +1 -1
- metadata +35 -1
data/docs/index.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Documentation"
|
|
3
|
+
nav_group: Start here
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# TypedEAV documentation
|
|
7
|
+
|
|
8
|
+
Add runtime-defined custom fields to Active Record models using native PostgreSQL
|
|
9
|
+
columns for scalar values and JSONB for collections. Define fields globally or
|
|
10
|
+
per tenant, validate input, and query values through Active Record relations.
|
|
11
|
+
|
|
12
|
+
## Start here
|
|
13
|
+
|
|
14
|
+
1. [Install and try TypedEAV](getting-started.md).
|
|
15
|
+
2. [Define fields, assign values, and build forms](guides/usage.md).
|
|
16
|
+
3. [Configure tenant scoping](guides/scoping.md) if your application has tenants.
|
|
17
|
+
4. [Filter, sort, and summarize values](guides/queries.md).
|
|
18
|
+
|
|
19
|
+
## Guides
|
|
20
|
+
|
|
21
|
+
| Task | Guide |
|
|
22
|
+
|---|---|
|
|
23
|
+
| Choose field types and create custom types | [Fields and validation](guides/fields.md) |
|
|
24
|
+
| Build forms, manage fields, and inspect pending changes | [Reading, writing, and forms](guides/usage.md) |
|
|
25
|
+
| Configure tenants and inspect effective definitions | [Scoping and partitions](guides/scoping.md) |
|
|
26
|
+
| Search and summarize custom values | [Queries](guides/queries.md) |
|
|
27
|
+
| Read and update many records | [Bulk operations](guides/bulk-operations.md) |
|
|
28
|
+
| Map CSV rows to custom fields | [CSV mapping](guides/csv-import.md) |
|
|
29
|
+
| Move field definitions between environments | [Schema portability](guides/schema.md) |
|
|
30
|
+
| React to changes and keep audit history | [Events and versioning](guides/events-and-versioning.md) |
|
|
31
|
+
| Evaluate indexes and performance tradeoffs | [Storage and performance](guides/performance.md) |
|
|
32
|
+
| Upgrade an existing installation | [Upgrading](guides/upgrading.md) |
|
|
33
|
+
|
|
34
|
+
## Reference and development
|
|
35
|
+
|
|
36
|
+
- [Public API and configuration](reference/index.md)
|
|
37
|
+
- [Architecture](guides/architecture.md) and [design decisions](adr/index.md)
|
|
38
|
+
- [Development and test isolation](guides/development.md)
|
|
39
|
+
- [Maintaining and publishing these docs](maintaining.md)
|
|
40
|
+
- [Changelog](changelog.md)
|
|
41
|
+
- [Source and issues](https://github.com/dchuk/typed_eav)
|
|
42
|
+
|
|
43
|
+
These pages describe the code on the default branch. Check the changelog and
|
|
44
|
+
release tag when using an older gem version.
|
data/docs/maintaining.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Maintainers"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Maintaining and publishing the documentation
|
|
6
|
+
|
|
7
|
+
## Update docs with the API
|
|
8
|
+
|
|
9
|
+
Review documentation after every repository change, including code, tests, dependencies,
|
|
10
|
+
configuration, tooling, CI, migrations, and releases. Update affected pages in
|
|
11
|
+
the same change; if reader-facing behavior is unchanged, explain why no docs
|
|
12
|
+
update was needed in the handoff. Record user-visible changes in the root
|
|
13
|
+
`CHANGELOG.md` under Unreleased. A public API change includes its documentation
|
|
14
|
+
in the same change. Keep the
|
|
15
|
+
README focused on installation and discovery; maintain detailed usage here.
|
|
16
|
+
|
|
17
|
+
For each public capability, document a practical example, accepted inputs and
|
|
18
|
+
defaults, return value, and relevant failure behavior. Link its API reference to
|
|
19
|
+
its guide. Check claims against implementation and specs, especially transaction,
|
|
20
|
+
NULL, tenant, and callback behavior. A method being mentioned is not sufficient
|
|
21
|
+
coverage if users cannot work out how to call it.
|
|
22
|
+
|
|
23
|
+
Add new pages to the [documentation home](index.md) or the
|
|
24
|
+
[reference index](reference/index.md). Keep Markdown links relative between
|
|
25
|
+
published pages; `jekyll-relative-links` converts them to site URLs. Link to
|
|
26
|
+
GitHub for files outside `docs/`. Give new pages YAML front matter with a title
|
|
27
|
+
so Jekyll renders them. The sidebar automatically lists pages by `nav_group`
|
|
28
|
+
(assigned by folder defaults in `_config.yml`, or overridden in front matter).
|
|
29
|
+
Use `nav_exclude: true` for supporting pages that should be reachable only through
|
|
30
|
+
a summary page. Individual ADRs use this setting; their user-facing summary
|
|
31
|
+
appears once under Project. The active page is highlighted; mobile navigation uses an expandable menu.
|
|
32
|
+
|
|
33
|
+
The [changelog](changelog.md) is generated at build time from the root
|
|
34
|
+
`CHANGELOG.md` by `_plugins/changelog.rb`. Edit that source file only and rebuild
|
|
35
|
+
to preview changes. The workflow also runs when that file changes. Use ordinary Markdown headings and fenced examples.
|
|
36
|
+
|
|
37
|
+
## Preview locally
|
|
38
|
+
|
|
39
|
+
The documentation dependencies are isolated from the gem's development bundle.
|
|
40
|
+
From the gem repository:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
cd docs
|
|
44
|
+
bundle install
|
|
45
|
+
bundle exec jekyll serve
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Open `http://localhost:4000/typed_eav/`. The default layout uses the Minima theme;
|
|
49
|
+
there is no separate frontend application to maintain.
|
|
50
|
+
|
|
51
|
+
To build and check links from the repository root:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
BUNDLE_GEMFILE=docs/Gemfile bundle exec jekyll build --source docs --destination docs/_site
|
|
55
|
+
python3 script/check_docs_site.py docs/_site /typed_eav
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The checker verifies local page/asset targets and heading anchors in generated
|
|
59
|
+
HTML. It does not make network requests or certify the accuracy of examples.
|
|
60
|
+
Review examples against the relevant gem specs as part of each change.
|
|
61
|
+
|
|
62
|
+
## Publish on GitHub Pages
|
|
63
|
+
|
|
64
|
+
The repository includes `.github/workflows/docs.yml`. Pull requests build and
|
|
65
|
+
check the site; pushes to `main` and manual runs on `main` also deploy it.
|
|
66
|
+
|
|
67
|
+
1. Commit and push the documentation and workflow to the gem repository.
|
|
68
|
+
2. In the repository's **Settings → Pages**, set **Source** to **GitHub Actions**.
|
|
69
|
+
3. Run the **Documentation** workflow on `main`, or push a documentation change.
|
|
70
|
+
4. Check the deployment URL in the workflow's `github-pages` environment.
|
|
71
|
+
|
|
72
|
+
The configured project URL is `https://dchuk.github.io/typed_eav/`. It becomes
|
|
73
|
+
available after the first successful deployment. For a different repository or
|
|
74
|
+
custom domain, update `url` and `baseurl` in `_config.yml` and the link-check
|
|
75
|
+
prefix in the workflow.
|
|
76
|
+
|
|
77
|
+
The site includes guides, references, and ADRs. Internal goal plans and
|
|
78
|
+
`improvement-program.md` are excluded, as are dependency and build files. Build
|
|
79
|
+
output is ignored by Git; GitHub Actions uploads the generated site directly.
|
|
80
|
+
|
|
81
|
+
See GitHub's [custom Pages workflow documentation](https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages)
|
|
82
|
+
for repository permissions and deployment settings.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Public API reference"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Public API reference
|
|
6
|
+
|
|
7
|
+
This is an index of application-facing entry points. Linked guides explain
|
|
8
|
+
examples, supported types, validation, and transaction boundaries. Internal
|
|
9
|
+
query builders, dispatchers, caches, and callback methods are not extension APIs.
|
|
10
|
+
|
|
11
|
+
## Host models and records
|
|
12
|
+
|
|
13
|
+
Declare `has_typed_eav(scope_method: nil, parent_scope_method: nil, types: nil,
|
|
14
|
+
versioned: false)` on an Active Record model. Scope methods name record accessors;
|
|
15
|
+
`parent_scope_method` requires `scope_method`. `types: nil` allows registered
|
|
16
|
+
types; an array restricts them. Versioning additionally requires the global
|
|
17
|
+
boot-time switch. Use the host's `polymorphic_name` for `entity_type`.
|
|
18
|
+
|
|
19
|
+
| Record method | Contract |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| `typed_values` | Active Record association; normal saves validate and persist values with the host. |
|
|
22
|
+
| `typed_eav_definitions` | Visible definitions for this record's partition, including same-name candidates. |
|
|
23
|
+
| `typed_eav_scope`, `typed_eav_parent_scope` | Configured accessor values normalized to strings, or `nil`. |
|
|
24
|
+
| `initialize_typed_values` | Build missing effective fields with defaults in memory; returns `typed_values`. Save separately. |
|
|
25
|
+
| `typed_eav_value(name)` | Logical Ruby value, or `nil` when absent. |
|
|
26
|
+
| `set_typed_eav_value(name, value)` | Stage a value by effective field name; unknown names are ignored. Save separately. |
|
|
27
|
+
| `typed_eav_hash` | Hash of field names to logical values. |
|
|
28
|
+
| `typed_eav_attributes=` / `typed_eav=` | Named entries such as `[{name: "age", value: 30}]`; supports `_destroy`. |
|
|
29
|
+
| `typed_values_attributes=` | Rails nested attributes using `field_id`, optional Value `id`, `value`, and `_destroy`. |
|
|
30
|
+
| `typed_eav_changes` | Pending logical changes as `{name => [before, after]}`. |
|
|
31
|
+
| `saved_typed_eav_changes` | Logical changes from the latest successful host save; reload/rollback clears them. |
|
|
32
|
+
|
|
33
|
+
See [reading, writing, and forms](../guides/usage.md),
|
|
34
|
+
[defaults](../guides/usage.md#defaults-for-new-and-existing-records), and [scoping](../guides/scoping.md).
|
|
35
|
+
|
|
36
|
+
## Host queries
|
|
37
|
+
|
|
38
|
+
These methods are available on the host class and through Active Record relations.
|
|
39
|
+
The query methods below (including `typed_eav_definitions`) accept `scope:` and
|
|
40
|
+
`parent_scope:`. Omitted keywords use ambient resolution; explicit `nil` selects
|
|
41
|
+
the global axis. These select **field definitions**, not authorized host rows:
|
|
42
|
+
start with an appropriately filtered host relation.
|
|
43
|
+
|
|
44
|
+
| Method | Result and defaults |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `where_typed_eav(*filters, include_missing: false)` | Active Record relation; filters use `name`, `op` (default `:eq`), and `value`. |
|
|
47
|
+
| `with_field(name, operator_or_value = nil, value = nil, include_missing: false)` | Single-filter relation; two-argument non-Symbol value implies equality. |
|
|
48
|
+
| `order_typed_eav(name, direction: :asc, nulls: :last)` | Relation ordered by a supported scalar field, then host primary key. Replaces prior ordering. |
|
|
49
|
+
| `distinct_typed_eav_values(name, limit: 100)` | Array of distinct scalar values in database order. |
|
|
50
|
+
| `count_distinct_typed_eav_values(name)` | Integer distinct count, including an explicit NULL category. |
|
|
51
|
+
| `typed_eav_value_counts(name, limit: 100)` | Hash of scalar values to counts. |
|
|
52
|
+
| `aggregate_typed_eav(name, operation:)` | `:min`, `:max`, or `:sum` for Integer/Decimal/Percentage; typed number or `nil` for empty min/max. |
|
|
53
|
+
| `typed_eav_definitions` | Relation of visible field definitions; does not collapse names. |
|
|
54
|
+
|
|
55
|
+
Missing rows differ from explicit NULL rows. `include_missing: true` broadens
|
|
56
|
+
`:is_null` and is ignored by other operators. Scalar APIs reject unsupported
|
|
57
|
+
field families and all-partition ambiguity with `ArgumentError`. See
|
|
58
|
+
[queries](../guides/queries.md) for operators, NULL behavior, limits, and errors.
|
|
59
|
+
|
|
60
|
+
## Bulk operations
|
|
61
|
+
|
|
62
|
+
| Host class method | Result and defaults |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `typed_eav_hash_for(records, fields: nil, source: :database)` | `{record.id => {field_name => value}}`; optional selected field names; `source: :preloaded` reads loaded associations. |
|
|
65
|
+
| `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}}`. |
|
|
66
|
+
| `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. |
|
|
67
|
+
| `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. |
|
|
68
|
+
|
|
69
|
+
Normal bulk writes collect validation failures per record; an unexpected exception
|
|
70
|
+
can roll back the active transaction. `transaction: :chunks` requires a positive
|
|
71
|
+
`chunk_size`; prior chunks remain committed on later failure. See
|
|
72
|
+
[bulk operations](../guides/bulk-operations.md) before choosing either write path.
|
|
73
|
+
|
|
74
|
+
## Field definitions and values
|
|
75
|
+
|
|
76
|
+
Use `TypedEAV::Field::<Type>.create!` and ordinary Active Record updates for field
|
|
77
|
+
metadata; `field_options` holds Select/MultiSelect choices. The
|
|
78
|
+
[fields guide](../guides/fields.md) covers every built-in type and its options.
|
|
79
|
+
|
|
80
|
+
| API | Purpose |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `field.default_value` / `default_value=` | Read/set the logical default. Explicit value assignment can override it with `nil`. |
|
|
83
|
+
| `field.backfill_default!(relation: nil)` | Synchronously apply a configured default to eligible existing hosts in batches; no count/result contract. |
|
|
84
|
+
| `field.destroy!` | Apply the field's `field_dependent` policy. |
|
|
85
|
+
| `field.destroy_with_values_in_batches!(batch_size: 1_000)` | Resumable deletion for persisted `field_dependent: :destroy` fields; requires no open transaction. |
|
|
86
|
+
| `field.move_higher`, `move_lower`, `move_to_top`, `move_to_bottom`, `insert_at(position)` | Reorder within the field's partition. |
|
|
87
|
+
| `field.field_type_name`, `display_name`, `array_field?`, `optionable?`, `allowed_option_values` | Metadata for rendering and field-management interfaces. |
|
|
88
|
+
| `field.cast(raw)` | Custom-type protocol returning `[cast_value, invalid]`; casting alone does not establish validity. |
|
|
89
|
+
| `value.value` / `value=` | Read/write the field's logical value, including multi-cell types. |
|
|
90
|
+
| `value.history` | Versions ordered newest first by timestamp and ID. |
|
|
91
|
+
| `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. |
|
|
92
|
+
|
|
93
|
+
See [default initialization and backfill](../guides/usage.md#defaults-for-new-and-existing-records),
|
|
94
|
+
[field deletion](../guides/events-and-versioning.md#public-callback-slots), and
|
|
95
|
+
[custom types](../guides/fields.md#custom-field-types) for their contracts. Full history after Value deletion requires querying
|
|
96
|
+
`TypedEAV::ValueVersion` by entity and field identity; see
|
|
97
|
+
[events and versioning](../guides/events-and-versioning.md).
|
|
98
|
+
|
|
99
|
+
## Schema and CSV
|
|
100
|
+
|
|
101
|
+
| API | Result |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| `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. |
|
|
104
|
+
| `TypedEAV::SchemaPortability.preview_schema(hash, on_conflict: :error)` | Read-only JSON-safe comparison and predicted actions; advisory, not a reservation or validation guarantee. |
|
|
105
|
+
| `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. |
|
|
106
|
+
| `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. |
|
|
107
|
+
| `TypedEAV::CSVMapper.row_to_attributes(row, mapping, fields_by_name: nil)` | Result with frozen `attributes`/`errors` Hashes and `success?`/`failure?`. Does not save records. |
|
|
108
|
+
|
|
109
|
+
`Field::Base.export_schema` and `.import_schema` remain compatible delegators.
|
|
110
|
+
Conflict policies are `:error`, `:skip`, and `:overwrite`; type swaps are refused.
|
|
111
|
+
CSV mapping uses uniformly String header keys or Integer index keys, with field
|
|
112
|
+
names as values. Typed mode casts via supplied definitions, reports cast errors,
|
|
113
|
+
and skips unknown fields. Normal model validation must still run.
|
|
114
|
+
See [schema portability](../guides/schema.md) and [CSV imports](../guides/csv-import.md).
|
|
115
|
+
|
|
116
|
+
## Partition helpers
|
|
117
|
+
|
|
118
|
+
`TypedEAV::Partition` expects explicitly resolved scope values; it does not consult
|
|
119
|
+
ambient scope. Visibility methods accept `scope: nil`, `parent_scope: nil`, and
|
|
120
|
+
`mode: :partition`. Use `mode: :all_partitions` only for an authorized admin bypass.
|
|
121
|
+
Invalid modes and orphan parent scopes raise `ArgumentError` in partition mode.
|
|
122
|
+
|
|
123
|
+
| Method | Result |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| `visible_fields(entity_type: nil, ...)` | Field relation, including global, scope-only, and full-tuple candidates. |
|
|
126
|
+
| `effective_fields_by_name(entity_type:, ...)` | `{name => field}` with most-specific precedence; all-partitions mode instead returns `{name => [fields]}`. |
|
|
127
|
+
| `definitions_by_name(defs)` | Collapse supplied definitions by name, most-specific winning. Supply only the intended visible set. |
|
|
128
|
+
| `definitions_multimap_by_name(defs)` | Group supplied definitions as `{name => [fields]}` without collapsing. |
|
|
129
|
+
| `visible_sections(entity_type:, ...)` | Relation of sections visible to the tuple. |
|
|
130
|
+
| `find_visible_section!(id, entity_type:, ...)` | Visible Section, or `ActiveRecord::RecordNotFound`. |
|
|
131
|
+
|
|
132
|
+
These helpers constrain definition visibility; application authorization still
|
|
133
|
+
belongs to the caller. See [scoping](../guides/scoping.md).
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuration reference"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Configuration reference
|
|
6
|
+
|
|
7
|
+
Configure the gem in a Rails initializer:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
TypedEAV.configure do |config|
|
|
11
|
+
config.scope_resolver = -> { [Current.account&.id, Current.workspace&.id] }
|
|
12
|
+
config.require_scope = true
|
|
13
|
+
end
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The example assumes those are the same partition identifiers returned by the
|
|
17
|
+
host's declared accessors. `TypedEAV.config` returns the configuration object;
|
|
18
|
+
`configure` also accepts a block.
|
|
19
|
+
|
|
20
|
+
| Setting | Default | Contract |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `scope_resolver` | Auto-detect `ActsAsTenant` | Callable returning `nil` or exactly `[scope, parent_scope]`. Default returns `[ActsAsTenant.current_tenant, nil]` when available, otherwise `nil`. Bare scalars raise `ArgumentError`. |
|
|
23
|
+
| `require_scope` | `true` | Scoped host class queries raise `TypedEAV::ScopeRequired` when scope cannot be resolved. |
|
|
24
|
+
| `versioning` | `false` | Boot-time master switch for transactional audit callbacks; host must also declare `versioned: true`. |
|
|
25
|
+
| `actor_resolver` | `nil` | Optional callable supplying audit actor identity. Missing actor is allowed; applications can enforce stricter requirements in the resolver. |
|
|
26
|
+
| `on_value_change` | `nil` | `->(value, change_type, context) { ... }`; after commit, with `:create`, `:update`, or `:destroy`. |
|
|
27
|
+
| `on_field_change` | `nil` | `->(field, change_type) { ... }`; after commit, with `:create`, `:update`, `:destroy`, or `:rename`. |
|
|
28
|
+
| `on_image_attached` | `nil` | `->(value, blob) { ... }`; image attachment notification after commit, when Active Storage is available. |
|
|
29
|
+
|
|
30
|
+
Public callback errors are logged rather than propagated to the completed save.
|
|
31
|
+
Versioning is independent of the public callback slots. Configure the versioning
|
|
32
|
+
switch before the engine installs callbacks, not dynamically per request.
|
|
33
|
+
See [events and versioning](../guides/events-and-versioning.md) for ordering,
|
|
34
|
+
actor normalization, payloads, and audit transaction guarantees.
|
|
35
|
+
|
|
36
|
+
## Field type registration
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
TypedEAV.configure do |config|
|
|
40
|
+
config.register_field_type :phone, "MyApp::Fields::Phone"
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`config.field_types` maps type-name Symbols to class-name Strings;
|
|
45
|
+
`config.type_names` lists registered names; `config.field_class_for(:phone)`
|
|
46
|
+
constantizes a registered class and raises `ArgumentError` for an unknown type.
|
|
47
|
+
Use registration to extend built-ins and the host macro's `types:` option to
|
|
48
|
+
restrict a model. See [custom field types](../guides/fields.md).
|
|
49
|
+
|
|
50
|
+
## Block-scoped state
|
|
51
|
+
|
|
52
|
+
| API | Contract |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `TypedEAV.with_scope(value) { ... }` | Temporary ambient scope; accepts a scalar, `[scope, parent_scope]`, or `nil`. Nested blocks restore prior state. |
|
|
55
|
+
| `TypedEAV.current_scope` | Resolved normalized tuple, or `nil`; consults the block stack before the resolver. |
|
|
56
|
+
| `TypedEAV.unscoped { ... }` | Explicit all-partition query mode; differs from `scope: nil` (global definitions only). |
|
|
57
|
+
| `TypedEAV.unscoped?` | Whether that bypass is active. |
|
|
58
|
+
| `TypedEAV.with_context(**kwargs) { ... }` | Temporary merged context for value events and versions; nested blocks restore prior state. |
|
|
59
|
+
| `TypedEAV.current_context` | Frozen current context Hash, empty when unset. |
|
|
60
|
+
|
|
61
|
+
Scope resolution is for field definitions. Continue to filter and authorize host
|
|
62
|
+
records in the application. Scalar sorting and summaries reject all-partition
|
|
63
|
+
mode because same-name definitions are ambiguous. See
|
|
64
|
+
[scoping](../guides/scoping.md) and [queries](../guides/queries.md).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Reference"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Reference
|
|
6
|
+
|
|
7
|
+
Use these pages to locate a method, check a default, or find its detailed guide.
|
|
8
|
+
|
|
9
|
+
- [Public API](api.md): host records, queries, bulk operations, fields, schema/CSV, and partition helpers.
|
|
10
|
+
- [Configuration](configuration.md): initializer settings, type registration, scope blocks, and event context.
|
|
11
|
+
|
|
12
|
+
For an introduction, start with the [documentation home](../index.md). Reference
|
|
13
|
+
entries describe application-facing contracts rather than every Ruby method in
|
|
14
|
+
the implementation.
|
|
15
|
+
|
|
16
|
+
- [Design decisions](../adr/index.md): the rationale behind user-facing behavior and extension choices.
|
data/lib/typed_eav/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: typed_eav
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dchuk
|
|
@@ -55,6 +55,7 @@ files:
|
|
|
55
55
|
- CHANGELOG.md
|
|
56
56
|
- MIT-LICENSE
|
|
57
57
|
- README.md
|
|
58
|
+
- RELEASING.md
|
|
58
59
|
- Rakefile
|
|
59
60
|
- app/models/typed_eav/application_record.rb
|
|
60
61
|
- app/models/typed_eav/field/base.rb
|
|
@@ -95,6 +96,38 @@ files:
|
|
|
95
96
|
- db/migrate/20260507000000_add_label_to_typed_eav_fields.rb
|
|
96
97
|
- db/migrate/20260712000000_enforce_parent_scope_invariant.rb
|
|
97
98
|
- db/migrate/20260816000000_use_partial_covering_scalar_indexes.rb
|
|
99
|
+
- docs/adr/0001-collapse-column-mapping-stack.md
|
|
100
|
+
- docs/adr/0002-entity-query-orchestration.md
|
|
101
|
+
- docs/adr/0003-keep-event-dispatcher-broker.md
|
|
102
|
+
- docs/adr/0004-field-family-intermediate-bases.md
|
|
103
|
+
- docs/adr/0005-keep-phase-six-modules-independent.md
|
|
104
|
+
- docs/adr/0006-include-missing-via-set-complement.md
|
|
105
|
+
- docs/adr/0007-visibility-versus-mutation-relations.md
|
|
106
|
+
- docs/adr/0008-partial-covering-scalar-indexes.md
|
|
107
|
+
- docs/adr/0009-string-search-indexing.md
|
|
108
|
+
- docs/adr/0010-planner-statistics-policy.md
|
|
109
|
+
- docs/adr/0011-multi-filter-query-strategy.md
|
|
110
|
+
- docs/adr/0012-cross-scope-administrative-query-policy.md
|
|
111
|
+
- docs/adr/0013-durable-versioning-and-field-deletion.md
|
|
112
|
+
- docs/adr/index.md
|
|
113
|
+
- docs/getting-started.md
|
|
114
|
+
- docs/guides/architecture.md
|
|
115
|
+
- docs/guides/bulk-operations.md
|
|
116
|
+
- docs/guides/csv-import.md
|
|
117
|
+
- docs/guides/development.md
|
|
118
|
+
- docs/guides/events-and-versioning.md
|
|
119
|
+
- docs/guides/fields.md
|
|
120
|
+
- docs/guides/performance.md
|
|
121
|
+
- docs/guides/queries.md
|
|
122
|
+
- docs/guides/schema.md
|
|
123
|
+
- docs/guides/scoping.md
|
|
124
|
+
- docs/guides/upgrading.md
|
|
125
|
+
- docs/guides/usage.md
|
|
126
|
+
- docs/index.md
|
|
127
|
+
- docs/maintaining.md
|
|
128
|
+
- docs/reference/api.md
|
|
129
|
+
- docs/reference/configuration.md
|
|
130
|
+
- docs/reference/index.md
|
|
98
131
|
- lib/generators/typed_eav/install/install_generator.rb
|
|
99
132
|
- lib/generators/typed_eav/scaffold/scaffold_generator.rb
|
|
100
133
|
- lib/generators/typed_eav/scaffold/templates/config/initializers/typed_eav.rb
|
|
@@ -178,6 +211,7 @@ licenses:
|
|
|
178
211
|
metadata:
|
|
179
212
|
homepage_uri: https://github.com/dchuk/typed_eav
|
|
180
213
|
source_code_uri: https://github.com/dchuk/typed_eav
|
|
214
|
+
documentation_uri: https://dchuk.github.io/typed_eav/
|
|
181
215
|
changelog_uri: https://github.com/dchuk/typed_eav/blob/main/CHANGELOG.md
|
|
182
216
|
bug_tracker_uri: https://github.com/dchuk/typed_eav/issues
|
|
183
217
|
allowed_push_host: https://rubygems.org
|