AshVersioned.Resource
Copy MarkdownConfigures a resource for versioning. The source table gets a stable resource identifier, a version number, and a flag marking a row as the latest version, and mutations append new rows instead of updating in place.
Versioned resources must already have the following fields declared in attributes.
- A surrogate primary key (
uuid_v7_primary_key,integer_primary_key, or one already on a ported table). Composite keys are not supported. - Create and update timestamps (usually
:inserted_atand:updated_at) with any non-null datetime-family attribute.
versioning
Configures SCD (type 2) version tracking on this resource.
Nested DSLs
Options
| Name | Type | Default | Docs |
|---|---|---|---|
create_timestamp_attribute | atom | :inserted_at | The name of the timestamp attribute used when inserting a new version. This reflects when this version became active. The attribute must already be defined in attributes. |
update_timestamp_attribute | atom | :updated_at | The name of the timestamp attribute updated when a version is marked stale. This reflects when this version became inactive. The attribute must already be defined in attributes. |
exclude_update_actions | list(atom) | [] | Update actions intentionally left as ordinary in-place updates instead of appending a new version. Every other update action on the resource is wired to append automatically. WARNING: This should only be used in exceptional circumstances, because it breaks the core promise of SCD (type 2) versioning: inactive versions don't change. |
exclude_read_actions | list(atom) | [] | Read actions that should skip the default latest (and archived) scoping applied to every other read action. This could include hand-declared audit or admin-facing actions that need to see stale and archived versions. |
history_action | atom | :version_history | The name of the generated read action that returns every version, ignoring the default latest/archived scoping. |
source_prefix | String.t | If specified, this prefix is applied to the underlying source of the generated AshVersioned fields. Fields adopting defined fields (define_attribute? false) or that declare source ignore this setting. elixir versioning do archive() source_prefix "vo_" end This is equivalent to: elixir versioning do archive :archived, source: :vo_archived identity :resource_id, source: :vo_resource_id latest :latest_version, source: :vo_latest_version version :version_number, source: :vo_version_number end The prefix is applied in front of any name given, so identity :mo_id would become identity :mo_id, source: :vo_mo_id. |
versioning.identity
identity name \\ :resource_idConfigures the identity held by every version of the same versioned resource; a "logical" primary key.
If omitted, this is equivalent to identity :resource_id.
Examples
identity :resource_ididentity do
origin :accepted
end
identity :resource_id, origin: :acceptedidentity :mo_id do
define_attribute? false
end
Arguments
| Name | Type | Default | Docs |
|---|---|---|---|
name | atom | :resource_id | The name of the identity attribute. |
Options
| Name | Type | Default | Docs |
|---|---|---|---|
define_attribute? | boolean | true | If set to false, the identity attribute is not created and one must be manually added to attributes, invalidating many other options. |
origin | :generated | :accepted | :generated | If not set or set as :generated, the value of the identity is generated on resource creation. If set to :accepted, the identity is an accepted parameter on every create action. |
type | any | :uuid_v7 | The type of the generated attribute. See Ash.Type for more details. Types other than :uuid and :uuid_v7 require that origin be set to :accepted. |
source | atom | The name of the field on the underlying data layer. |
Introspection
Target: AshVersioned.Resource.Identity
versioning.version
version name \\ :version_numberConfigures the monotonically increasing version number, starting at 0.
If omitted, this is equivalent to version :version_number.
Examples
version :version_numberversion :mo_version do
define_attribute? false
end
Arguments
| Name | Type | Default | Docs |
|---|---|---|---|
name | atom | :version_number | The name of the version attribute. |
Options
| Name | Type | Default | Docs |
|---|---|---|---|
define_attribute? | boolean | true | If set to false, the version attribute is not created and one must be manually added to attributes, invalidating many other options. |
source | atom | The name of the field on the underlying data layer. |
Introspection
Target: AshVersioned.Resource.Version
versioning.latest
latest name \\ :latest_versionConfigures the boolean flag marking the current version for this resource.
If omitted, this is equivalent to latest :latest_version.
Examples
latest :latest_versionlatest :mo_is_latest do
define_attribute? false
end
Arguments
| Name | Type | Default | Docs |
|---|---|---|---|
name | atom | :latest_version | The name of the latest attribute. |
Options
| Name | Type | Default | Docs |
|---|---|---|---|
define_attribute? | boolean | true | If set to false, the latest attribute is not created and one must be manually added to attributes, invalidating many other options. |
source | atom | The name of the field on the underlying data layer. |
Introspection
Target: AshVersioned.Resource.Latest
versioning.archive
archive attribute \\ :archivedDeclares this resource archivable, which makes every destroy action a soft?: true
destroy action.
If not set, defining destroy actions on the resource is a compile error.
Examples
archive :archivedarchive do
action :discard
end
Arguments
| Name | Type | Default | Docs |
|---|---|---|---|
attribute | atom | :archived | The name of the boolean attribute marking a version as archived. |
Options
| Name | Type | Default | Docs |
|---|---|---|---|
define_attribute? | boolean | true | If set to false, the archived attribute is not created and one must be manually added to attributes, invalidating many other options. |
action | atom | false | :archive | The name of a generated default destroy action, created using this name unless a destroy action is already defined (regardless of its name). Set to false to skip generating it unconditionally. |
read_action | atom | false | :get_with_archived | The name of a generated get_by read action that returns the latest version of a resource by its identity attribute, whether or not it's archived. This action is scoped to return the latest version of a resource. Skipped if an action with this name is already defined. Set to false to skip generating it unconditionally. |
unarchive | atom | false | :unarchive | The name of a generated update action that sets the archived to false, accepting no input. Skipped if an action with this name is already defined. Set to false to skip generating it unconditionally. |
exclude_read_actions | list(atom) | [] | Additional read actions (beyond read_action) that should skip the filtering archived resources while still respecting the latest version filtering. An action name only needs to appear here or in the top-level exclude_read_actions, not both. |
source | atom | The name of the field on the underlying data layer. |
Introspection
Target: AshVersioned.Resource.Archive
versioning.reference_actor
reference_actor nameCreates a :string attribute for storing the actor responsible for resource version
creation.
reference_actor can be used when the actor field holds heterogeneous ID spaces
(admin, customer, or sentinel values like "system") that may not resolve
to Ash resources. It works best with prefixed object ID strings (admin_QweRTy,
customer_Dv0rAk, etc.).
For more than one possible Ash resource actor type, use belongs_to_actor instead,
which discriminates by the actor type.
Examples
reference_actor :created_byreference_actor :created_by, transform: &MyApp.actor_reference/1Arguments
| Name | Type | Default | Docs |
|---|---|---|---|
name | atom | The name of the attribute to use for the actor. |
Options
| Name | Type | Default | Docs |
|---|---|---|---|
transform | (any -> any) | mfa | &AshVersioned.ReferenceActorValue.value_for/1 | A function or {module, function, args} to transform the actor into a suitable string reference. The default is AshVersioned.ReferenceActorValue.value_for/1. Use a different function when support for composite primary keys, prefixed keys, or some other requirement arises. |
allow_nil? | boolean | true | Whether this attribute can be nil. |
public? | boolean | false | Whether this attribute should be shown over public interfaces. |
Introspection
Target: AshVersioned.Resource.ReferenceActor
versioning.belongs_to_actor
belongs_to_actor name, destinationCreates a belongs_to relationship to the actor resource. When creating a new
version, associates the action's actor with the matching resource type. For
polymorphic or variant types, declare a belongs_to_actor for each type.
If your actor is not a resource, consider using reference_actor instead.
Examples
belongs_to_actor :edited_by, MyApp.Users.Authorbelongs_to_actor :reviewed_by, MyApp.Users.Author, domain: MyApp.UsersArguments
| Name | Type | Default | Docs |
|---|---|---|---|
name | atom | The name of the relationship to use for the actor. | |
destination | module | The resource of the actor (e.g. MyApp.Users.User) |
Options
| Name | Type | Default | Docs |
|---|---|---|---|
allow_nil? | boolean | true | Whether this relationship must always be present. The generated attribute will not allow nil values. |
domain | atom | The Domain module to use when working with the related entity. | |
attribute_type | any | :uuid | The type of the generated attribute. See Ash.Type for more. |
public? | boolean | false | Whether this relationship should be included in public interfaces |
define_attribute? | boolean | true | If set to false, an attribute is not created on the resource for this relationship, and one must be manually added in attributes, invalidating many other options. |
on_delete | :delete | :nilify | :nothing | :restrict | {:nilify, atom | list(atom)} | :nothing | The action to take on this row when the actor is deleted. Can also be {:nilify, columns} to nilify specific columns (Postgres 15+ only). Only relevant for resources using a SQL data layer. Has no impact when destination is an AshVersioned.Resource. |