View Source Ash.Resource.Dsl (ash v2.0.0-rc.13)
The built in resource DSL.
dsl-documentation
DSL Documentation
index
Index
- attributes
- attribute
- create_timestamp
- update_timestamp
- integer_primary_key
- uuid_primary_key
- relationships
- has_one
- has_many
- many_to_many
- belongs_to
- actions
- create
- change
- validate
- argument
- metadata
- read
- argument
- prepare
- pagination
- update
- change
- validate
- metadata
- argument
- destroy
- change
- validate
- metadata
- argument
- create
- code_interface
- define
- resource
- identities
- identity
- changes
- change
- preparations
- prepare
- validations
- validate
- aggregates
- count
- first
- sum
- list
- calculations
- calculate
- argument
- calculate
- multitenancy
docs
Docs
attributes
attributes
A section for declaring attributes on the resource.
Examples:
attributes do
uuid_primary_key :id
attribute :first_name, :string do
allow_nil? false
end
attribute :last_name, :string do
allow_nil? false
end
attribute :email, :string do
allow_nil? false
constraints [
match: ~r/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$/
]
end
attribute :type, :atom do
constraints [
one_of: [:admin, :teacher, :student]
]
end
create_timestamp :inserted_at
update_timestamp :updated_at
end
Imports:
attribute
attribute
Declares an attribute on the resource.
Examples:
attribute :name, :string do
allow_nil? false
end
:name
- The name of the attribute.:type
- The type of the attribute.:constraints
- Constraints to provide to the type when casting the value. See the type's documentation for more information.:description
- An optional description for the attribute.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:source
- If the field should be mapped to a different name in the data layer. Support varies by data layer.:always_select?
- Whether or not to ensure this attribute is always selected when reading from the database. The default value isfalse
.:primary_key?
- Whether or not the attribute is part of the primary key (one or more fields that uniquely identify a resource)." If primary_key? is true, allow_nil? must be false. The default value isfalse
.:allow_nil?
- Whether or not the attribute can be set to nil. The default value istrue
.:generated?
- Whether or not the value may be generated by the data layer. The default value isfalse
.:writable?
- Whether or not the value can be written to. The default value istrue
.:private?
- Whether or not the attribute can be provided as input, or will be shown when extensions work with the resource (i.e won't appear in a web api). The default value isfalse
.:default
- A value to be set on all creates, unless a value is being provided already.:update_default
- A value to be set on all updates, unless a value is being provided already.:filterable?
- Whether or not the attribute can be referenced in filters. The default value istrue
.:match_other_defaults?
- Ensures that other attributes that use the same "lazy" default (a function or an mfa), use the same default value. Has no effect unlessdefault
is a zero argument function. For example, create and update timestamps use this option, and have the same lazy function&DateTime.utc_now/0
, so they get the same value, instead of having slightly different timestamps. The default value isfalse
.
create_timestamp
create_timestamp
Declares a non-writable attribute with a create default of &DateTime.utc_now/0
Examples:
create_timestamp :inserted_at
:name
- The name of the attribute.:type
- The type of the attribute. The default value isAsh.Type.UtcDatetimeUsec
.:constraints
- Constraints to provide to the type when casting the value. See the type's documentation for more information.:description
- An optional description for the attribute.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:source
- If the field should be mapped to a different name in the data layer. Support varies by data layer.:always_select?
- Whether or not to ensure this attribute is always selected when reading from the database. The default value isfalse
.:primary_key?
- Whether or not the attribute is part of the primary key (one or more fields that uniquely identify a resource)." If primary_key? is true, allow_nil? must be false. The default value isfalse
.:allow_nil?
- Whether or not the attribute can be set to nil. The default value isfalse
.:generated?
- Whether or not the value may be generated by the data layer. The default value isfalse
.:writable?
- Whether or not the value can be written to. The default value isfalse
.:private?
- Whether or not the attribute can be provided as input, or will be shown when extensions work with the resource (i.e won't appear in a web api). The default value istrue
.:default
- A value to be set on all creates, unless a value is being provided already. The default value is&DateTime.utc_now/0
.:update_default
- A value to be set on all updates, unless a value is being provided already.:filterable?
- Whether or not the attribute can be referenced in filters. The default value istrue
.:match_other_defaults?
- Ensures that other attributes that use the same "lazy" default (a function or an mfa), use the same default value. Has no effect unlessdefault
is a zero argument function. For example, create and update timestamps use this option, and have the same lazy function&DateTime.utc_now/0
, so they get the same value, instead of having slightly different timestamps. The default value istrue
.
update_timestamp
update_timestamp
Declares a non-writable attribute with a create and update default of &DateTime.utc_now/0
Examples:
update_timestamp :inserted_at
:name
- The name of the attribute.:type
- The type of the attribute. The default value isAsh.Type.UtcDatetimeUsec
.:constraints
- Constraints to provide to the type when casting the value. See the type's documentation for more information.:description
- An optional description for the attribute.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:source
- If the field should be mapped to a different name in the data layer. Support varies by data layer.:always_select?
- Whether or not to ensure this attribute is always selected when reading from the database. The default value isfalse
.:primary_key?
- Whether or not the attribute is part of the primary key (one or more fields that uniquely identify a resource)." If primary_key? is true, allow_nil? must be false. The default value isfalse
.:allow_nil?
- Whether or not the attribute can be set to nil. The default value isfalse
.:generated?
- Whether or not the value may be generated by the data layer. The default value isfalse
.:writable?
- Whether or not the value can be written to. The default value isfalse
.:private?
- Whether or not the attribute can be provided as input, or will be shown when extensions work with the resource (i.e won't appear in a web api). The default value istrue
.:default
- A value to be set on all creates, unless a value is being provided already. The default value is&DateTime.utc_now/0
.:update_default
- A value to be set on all updates, unless a value is being provided already. The default value is&DateTime.utc_now/0
.:filterable?
- Whether or not the attribute can be referenced in filters. The default value istrue
.:match_other_defaults?
- Ensures that other attributes that use the same "lazy" default (a function or an mfa), use the same default value. Has no effect unlessdefault
is a zero argument function. For example, create and update timestamps use this option, and have the same lazy function&DateTime.utc_now/0
, so they get the same value, instead of having slightly different timestamps. The default value istrue
.
integer_primary_key
integer_primary_key
Declares a generated, non writable, non-nil, primary key column of type integer.
Generated integer primary keys must be supported by the data layer.
Examples:
integer_primary_key :id
:name
- The name of the attribute.:type
- The type of the attribute. The default value is:integer
.:constraints
- Constraints to provide to the type when casting the value. See the type's documentation for more information.:description
- An optional description for the attribute.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:source
- If the field should be mapped to a different name in the data layer. Support varies by data layer.:always_select?
- Whether or not to ensure this attribute is always selected when reading from the database. The default value isfalse
.:primary_key?
- Whether or not the attribute is part of the primary key (one or more fields that uniquely identify a resource)." If primary_key? is true, allow_nil? must be false. The default value istrue
.:generated?
- Whether or not the value may be generated by the data layer. The default value istrue
.:writable?
- Whether or not the value can be written to. The default value isfalse
.:private?
- Whether or not the attribute can be provided as input, or will be shown when extensions work with the resource (i.e won't appear in a web api). The default value isfalse
.:default
- A value to be set on all creates, unless a value is being provided already.:update_default
- A value to be set on all updates, unless a value is being provided already.:filterable?
- Whether or not the attribute can be referenced in filters. The default value istrue
.:match_other_defaults?
- Ensures that other attributes that use the same "lazy" default (a function or an mfa), use the same default value. Has no effect unlessdefault
is a zero argument function. For example, create and update timestamps use this option, and have the same lazy function&DateTime.utc_now/0
, so they get the same value, instead of having slightly different timestamps. The default value isfalse
.
uuid_primary_key
uuid_primary_key
Declares a non writable, non-nil, primary key column of type uuid, which defaults to Ash.UUID.generate/0
.
Examples:
uuid_primary_key :id
:name
- The name of the attribute.:type
- The type of the attribute. The default value is:uuid
.:constraints
- Constraints to provide to the type when casting the value. See the type's documentation for more information.:description
- An optional description for the attribute.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:source
- If the field should be mapped to a different name in the data layer. Support varies by data layer.:always_select?
- Whether or not to ensure this attribute is always selected when reading from the database. The default value isfalse
.:primary_key?
- Whether or not the attribute is part of the primary key (one or more fields that uniquely identify a resource)." If primary_key? is true, allow_nil? must be false. The default value istrue
.:generated?
- Whether or not the value may be generated by the data layer. The default value isfalse
.:writable?
- Whether or not the value can be written to. The default value isfalse
.:private?
- Whether or not the attribute can be provided as input, or will be shown when extensions work with the resource (i.e won't appear in a web api). The default value isfalse
.:default
- A value to be set on all creates, unless a value is being provided already. The default value is&Ash.UUID.generate/0
.:update_default
- A value to be set on all updates, unless a value is being provided already.:filterable?
- Whether or not the attribute can be referenced in filters. The default value istrue
.:match_other_defaults?
- Ensures that other attributes that use the same "lazy" default (a function or an mfa), use the same default value. Has no effect unlessdefault
is a zero argument function. For example, create and update timestamps use this option, and have the same lazy function&DateTime.utc_now/0
, so they get the same value, instead of having slightly different timestamps. The default value isfalse
.
relationships
relationships
A section for declaring relationships on the resource.
Relationships are a core component of resource oriented design. Many components of Ash
will use these relationships. A simple use case is loading relationships (done via the Ash.Query.load/2
).
Examples:
relationships do
belongs_to :post, MyApp.Post do
primary_key? true
end
belongs_to :category, MyApp.Category do
primary_key? true
end
end
relationships do
belongs_to :author, MyApp.Author
many_to_many :categories, MyApp.Category do
through MyApp.PostCategory
destination_attribute_on_join_resource :category_id
source_attribute_on_join_resource :post_id
end
end
relationships do
has_many :posts, MyApp.Post do
destination_attribute :author_id
end
has_many :composite_key_posts, MyApp.CompositeKeyPost do
destination_attribute :author_id
end
end
Imports:
has_one
has_one
Declares a has_one relationship. In a relational database, the foreign key would be on the other table.
Generally speaking, a has_one
also implies that the destination table is unique on that foreign key.
Examples:
# In a resource called `Word`
has_one :dictionary_entry, DictionaryEntry do
source_attribute :text
destination_attribute :word_text
end
:manual
- Allows for relationships that are fetched manually. WARNING: EXPERIMENTAL
Manual relationships do not support filters or aggregates at the moment. In the future, what we may do is allow the data layer to be configured with a hook that expresses how to implement this manual relationship at the data layer level, like providing a custom ecto join for ash_postgres. This is the simple groundwork for that.# in the resource relationships do has_many :somethings, MyApp.Something do manual {MyApp.FetchSomethings, [opt1: :value]} # or if there are no opts # manual MyApp.FetchSomethings end end # the implementation defmodule MyApp.FetchSomethings do use Ash.Resource.ManualRelationship def load(records, _opts, %{relationship: relationship}) do # Return a map of primary keys of the records to the related records. # This example is likely suboptimal because it does a separate fetch for # each record, whereas you likely want to try to fetch them all at once, # and then create the mapping from pkey values to related records # For example: # get the primary key primary_key = Ash.Resource.Info.primary_key(relationship.source) # e.g [:id] # key the records by primary key and the related records with that primary key {:ok, Map.new(records, fn record -> # the key is the pkey values, e.g `%{id: 1}` # the value is the related records for that record {Map.take(record, primary_key), get_related_records(record)} end)} end end
:no_attributes?
- If true, all existing entities are considered related, i.e this relationship is not based on any fields, andsource_attribute
anddestination_attribute
are ignored.
This can be very useful when combined with multitenancy. Specifically, if you have a tenant resource likeOrganization
, you can useno_attributes?
to do things likehas_many :employees, Employee, no_attributes?: true
, which lets you avoid having an unnecessaryorganization_id
field onEmployee
. The same works in reverse:has_one :organization, Organization, no_attributes?: true
allows relating the employee to their organization.
Some important caveats here:
- You can still manage relationships from one to the other, but "relate" and "unrelate" will have no effect, because there are no fields to change.
- Loading the relationship on a list of resources will not behave as expected in all circumstances involving multitenancy. For example,
if you get a list of
Organization
and then try to loademployees
, you would need to set a single tenant on the load query, meaning you'll get all organizations back with the set of employees from one tenant. This could eventually be solved, but for now it is considered an edge case.
:allow_nil?
- Marks the relationship as required. Has no effect on validations, but can inform extensions that there will always be a related entity. The default value istrue
.:name
- The name of the relationship:destination
- The destination resource:description
- An optional description for the relationship:destination_attribute
- The attribute on the related resource that should match thesource_attribute
configured on this resource.:validate_destination_attribute?
- Whether or not to validate that the destination field exists on the destination resource The default value istrue
.:source_attribute
- The field on this resource that should match thedestination_attribute
on the related resource. The default value is:id
.:relationship_context
- Context to be set on any queries or changesets generated for managing or querying this relationship.:private?
- Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:not_found_message
- A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.:writable?
- Whether or not the relationship may be managed. The default value istrue
.:read_action
- The read action on the destination resource to use when loading data and filtering.:api
- The API module to use when working with the related entity.:filter
- A filter to be applied when reading the relationship.:filterable?
- If set tofalse
, the relationship will not be usable in filters. The default value istrue
.:sort
- A sort statement to be applied when loading the relationship.:could_be_related_at_creation?
- Whether or not related values may exist for this relationship at creation. The default value isfalse
.:violation_message
- A message to show if there is a conflict with this relationship in the database on destroy. For example, if a record is deleted while related records still exist (and aren't configured to cascade deletes)
has_many
has_many
Declares a has_many relationship. There can be any number of related entities.
Examples:
# In a resource called `Word`
has_many :definitions, DictionaryDefinition do
source_attribute :text
destination_attribute :word_text
end
:manual
- Allows for relationships that are fetched manually. WARNING: EXPERIMENTAL
Manual relationships do not support filters or aggregates at the moment. In the future, what we may do is allow the data layer to be configured with a hook that expresses how to implement this manual relationship at the data layer level, like providing a custom ecto join for ash_postgres. This is the simple groundwork for that.# in the resource relationships do has_many :somethings, MyApp.Something do manual {MyApp.FetchSomethings, [opt1: :value]} # or if there are no opts # manual MyApp.FetchSomethings end end # the implementation defmodule MyApp.FetchSomethings do use Ash.Resource.ManualRelationship def load(records, _opts, %{relationship: relationship}) do # Return a map of primary keys of the records to the related records. # This example is likely suboptimal because it does a separate fetch for # each record, whereas you likely want to try to fetch them all at once, # and then create the mapping from pkey values to related records # For example: # get the primary key primary_key = Ash.Resource.Info.primary_key(relationship.source) # e.g [:id] # key the records by primary key and the related records with that primary key {:ok, Map.new(records, fn record -> # the key is the pkey values, e.g `%{id: 1}` # the value is the related records for that record {Map.take(record, primary_key), get_related_records(record)} end)} end end
:no_attributes?
- If true, all existing entities are considered related, i.e this relationship is not based on any fields, andsource_attribute
anddestination_attribute
are ignored.
This can be very useful when combined with multitenancy. Specifically, if you have a tenant resource likeOrganization
, you can useno_attributes?
to do things likehas_many :employees, Employee, no_attributes?: true
, which lets you avoid having an unnecessaryorganization_id
field onEmployee
. The same works in reverse:has_one :organization, Organization, no_attributes?: true
allows relating the employee to their organization.
Some important caveats here:
- You can still manage relationships from one to the other, but "relate" and "unrelate" will have no effect, because there are no fields to change.
- Loading the relationship on a list of resources will not behave as expected in all circumstances involving multitenancy. For example,
if you get a list of
Organization
and then try to loademployees
, you would need to set a single tenant on the load query, meaning you'll get all organizations back with the set of employees from one tenant. This could eventually be solved, but for now it is considered an edge case.
:name
- The name of the relationship:destination
- The destination resource:description
- An optional description for the relationship:destination_attribute
- The attribute on the related resource that should match thesource_attribute
configured on this resource.:validate_destination_attribute?
- Whether or not to validate that the destination field exists on the destination resource The default value istrue
.:source_attribute
- The field on this resource that should match thedestination_attribute
on the related resource. The default value is:id
.:relationship_context
- Context to be set on any queries or changesets generated for managing or querying this relationship.:private?
- Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:not_found_message
- A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.:writable?
- Whether or not the relationship may be managed. The default value istrue
.:read_action
- The read action on the destination resource to use when loading data and filtering.:api
- The API module to use when working with the related entity.:filter
- A filter to be applied when reading the relationship.:filterable?
- If set tofalse
, the relationship will not be usable in filters. The default value istrue
.:sort
- A sort statement to be applied when loading the relationship.:could_be_related_at_creation?
- Whether or not related values may exist for this relationship at creation. The default value isfalse
.:violation_message
- A message to show if there is a conflict with this relationship in the database on destroy. For example, if a record is deleted while related records still exist (and aren't configured to cascade deletes)
many_to_many
many_to_many
Declares a many_to_many relationship. Many to many relationships require a join resource.
A join resource is a resource that consists of a relationship to the source and destination of the many to many.
Examples:
# In a resource called `Word`
many_to_many :books, Book do
through BookWord
source_attribute :text
source_attribute_on_join_resource :word_text
destination_attribute :id
destination_attribute_on_join_resource :book_id
end
# And in `BookWord` (the join resource)
belongs_to :book, Book, primary_key?: true, allow_nil?: false
belongs_to :word, Word, primary_key?: true, allow_nil?: false
:source_attribute_on_join_resource
- Required. The attribute on the join resource that should line up withsource_attribute
on this resource.:destination_attribute_on_join_resource
- Required. The attribute on the join resource that should line up withdestination_attribute
on the related resource.:through
- Required. The resource to use as the join resource.:join_relationship
- The has_many relationship to the join resource. Defaults to <relationship_name>_join_assoc:name
- The name of the relationship:destination
- The destination resource:description
- An optional description for the relationship:destination_attribute
- The attribute on the related resource that should match thesource_attribute
configured on this resource. The default value is:id
.:validate_destination_attribute?
- Whether or not to validate that the destination field exists on the destination resource The default value istrue
.:source_attribute
- The field on this resource that should match thedestination_attribute
on the related resource. The default value is:id
.:relationship_context
- Context to be set on any queries or changesets generated for managing or querying this relationship.:private?
- Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:not_found_message
- A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.:writable?
- Whether or not the relationship may be managed. The default value istrue
.:read_action
- The read action on the destination resource to use when loading data and filtering.:api
- The API module to use when working with the related entity.:filter
- A filter to be applied when reading the relationship.:filterable?
- If set tofalse
, the relationship will not be usable in filters. The default value istrue
.:sort
- A sort statement to be applied when loading the relationship.:could_be_related_at_creation?
- Whether or not related values may exist for this relationship at creation. The default value isfalse
.:violation_message
- A message to show if there is a conflict with this relationship in the database on destroy. For example, if a record is deleted while related records still exist (and aren't configured to cascade deletes)
belongs_to
belongs_to
Declares a belongs_to relationship. In a relational database, the foreign key would be on the source table.
This creates a field on the resource with the corresponding name and type, unless define_attribute?: false
is provided.
Examples:
# In a resource called `Word`
belongs_to :dictionary_entry, DictionaryEntry do
source_attribute :text,
destination_attribute :word_text
end
:primary_key?
- Whether the generated attribute is, or is part of, the primary key of a resource. The default value isfalse
.:allow_nil?
- Whether this relationship must always be present, e.g: must be included on creation, and never removed (it may be modified). The generated attribute will not allow nil values. The default value istrue
.:attribute_writable?
- Whether the generated attribute will be marked as public & writable. The default value isfalse
.:define_attribute?
- If set tofalse
an attribute is not created on the resource for this relationship, and one must be manually added inattributes
, invalidating many other options. The default value istrue
.:attribute_type
- The type of the generated created attribute. The default value is:uuid
.:name
- The name of the relationship:destination
- The destination resource:description
- An optional description for the relationship:destination_attribute
- The attribute on the related resource that should match thesource_attribute
configured on this resource. The default value is:id
.:validate_destination_attribute?
- Whether or not to validate that the destination field exists on the destination resource The default value istrue
.:source_attribute
- The field on this resource that should match thedestination_attribute
on the related resource. - Defaults to <name>_id:relationship_context
- Context to be set on any queries or changesets generated for managing or querying this relationship.:private?
- Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:not_found_message
- A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.:writable?
- Whether or not the relationship may be managed. The default value istrue
.:read_action
- The read action on the destination resource to use when loading data and filtering.:api
- The API module to use when working with the related entity.:filter
- A filter to be applied when reading the relationship.:filterable?
- If set tofalse
, the relationship will not be usable in filters. The default value istrue
.:sort
- A sort statement to be applied when loading the relationship.:violation_message
- A message to show if there is a conflict with this relationship in the database on destroy. For example, if a record is deleted while related records still exist (and aren't configured to cascade deletes)
actions
actions
A section for declaring resource actions.
All manipulation of data through the underlying data layer happens through actions.
There are four types of action: create
, read
, update
, and destroy
. You may
recognize these from the acronym CRUD
. You can have multiple actions of the same
type, as long as they have different names. This is the primary mechanism for customizing
your resources to conform to your business logic. It is normal and expected to have
multiple actions of each type in a large application.
- create
- change
- validate
- argument
- metadata
- read
- argument
- prepare
- pagination
- update
- change
- validate
- metadata
- argument
- destroy
- change
- validate
- metadata
- argument
Examples:
actions do
create :signup do
argument :password, :string
argument :password_confirmation, :string
validate confirm(:password, :password_confirmation)
change {MyApp.HashPassword, []} # A custom implemented Change
end
read :me do
# An action that auto filters to only return the user for the current user
filter [id: actor(:id)]
end
update :update do
accept [:first_name, :last_name]
end
destroy do
change set_attribute(:deleted_at, &DateTime.utc_now/0)
# This tells it that even though this is a delete action, it
# should be treated like an update because `deleted_at` is set.
# This should be coupled with a `base_filter` on the resource
# or with the read actions having a `filter` for `is_nil: :deleted_at`
soft? true
end
end
Imports:
Ash.Resource.Change.Builtins
Ash.Resource.Preparation.Builtins
Ash.Resource.Validation.Builtins
Ash.Filter.TemplateHelpers
:defaults
- Creates a simple action of each specified type, with the same name as the type. These actions will be the primary actions, unless you've declared a different action of the same type that is explicitly set as primary.
By default, resources have no default actions. Embedded resources, however, have a default of all resource types.:default_accept
- A default value for theaccept
option for each action. Defaults to all public attributes.
create
create
Declares a create
action. For calling this action, see the Ash.Api
documentation.
Examples:
create :register do
primary? true
end
:allow_nil_input
- A list of attributes that would normally be required, but should not be for this action. They will still be validated just before the record is created.:name
- Required. The name of the action:primary?
- Whether or not this action should be used when no action is specified by the caller. The default value isfalse
.:description
- An optional description for the action:transaction?
- Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default totrue
.
Has no effect if the data layer does not support transactions, or if that data layer is already in a transaction.:touches_resources
- A list of resources that the action may touch, used when building transactions.:accept
- The list of attributes to accept. Defaults to all attributes on the resource:reject
- A list of attributes not to accept. This is useful if you want to say 'accept all but x'
If this is specified along withaccept
, then everything in theaccept
list minus any matches in thereject
list will be accepted.:require_attributes
- A list of attributes that would normallyallow_nil?
, to require for this action.
No need to include attributes that already do not allow nil?:error_handler
- Sets the error handler on the changeset. SeeAsh.Changeset.handle_errors/2
for more:manual?
- Instructs Ash to skip the actual update/create/destroy step at the data layer. See the manual action guides for more.
change
A change to be applied to the changeset.
Examples:
change relate_actor(:reporter)
change {MyCustomChange, :foo}
:only_when_valid?
- If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here. The default value isfalse
.:description
- An optional description for the change:change
- Required. The module and options for a change.:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but instead just result in this change being ignored. The default value is[]
.
validate
Declares a validation to be applied to the changeset.
Examples:
validate changing(:email)
:validation
- Required. The module/opts pair of the validation:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but will instead result in this validation being ignored. The default value is[]
.:only_when_valid?
- If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data. The default value isfalse
.:message
- If provided, overrides any message set by the validation error:description
- An optional description for the validation:before_action?
- If set totrue
, the validation will be run in a before_action hook The default value isfalse
.
argument
Declares an argument on the action
Examples:
argument :password_confirmation, :string
:name
- Required. The name of the argument:type
- Required. The type of the argument:description
- An optional description for the argument.:constraints
- Type constraints on the argument The default value is[]
.:allow_nil?
- Whether or not the argument value may be nil (or may be not provided) The default value istrue
.:private?
- Whether or not the argument should be suppliable by the client. The default value isfalse
.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:default
- The default value for the argument to take. It can be a zero argument function e.g&MyMod.my_fun/0
or a value
metadata
A special kind of attribute that is only added to specific actions. Nothing sets this value, it must be set in a custom
change via Ash.Resource.Info.put_metadata/3
.
Examples:
metadata :api_token, :string, allow_nil?: false
metadata :operation_id, :string, allow_nil?: false
:name
- Required. The name of the metadata:type
- Required. The type of the metadata:constraints
- Type constraints on the metadata The default value is[]
.:description
- An optional description for the metadata.:allow_nil?
- Whether or not the metadata may returnnil
The default value istrue
.:default
- The default value for the metadata to take. It can be a zero argument function e.g&MyMod.my_fun/0
or a value
read
read
Declares a read
action. For calling this action, see the Ash.Api
documentation.
Examples:
read :read_all do
primary? true
end
:filter
- A filter template that will be applied whenever the action is used. SeeAsh.Filter
for more on templates:manual
- Delegates running of the query to the provided module.:get?
- Expresses that this action innately only returns a single result. Can be used by extensions to validate that you have not hooked something up that expects a list to an action that can only return one thing. Used by the code interface when defining functions for read actions. The default value isfalse
.:modify_query
- Allows direct manipulation of the data layer query via an MFA.
The ash query and the data layer query will be provided as additional arguments. The result must be{:ok, new_data_layer_query} | {:error, error}
.
Here be dragons.:name
- Required. The name of the action:primary?
- Whether or not this action should be used when no action is specified by the caller. The default value isfalse
.:description
- An optional description for the action:transaction?
- Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default totrue
.
Has no effect if the data layer does not support transactions, or if that data layer is already in a transaction.:touches_resources
- A list of resources that the action may touch, used when building transactions.
argument
Declares an argument on the action
Examples:
argument :password_confirmation, :string
:name
- Required. The name of the argument:type
- Required. The type of the argument:description
- An optional description for the argument.:constraints
- Type constraints on the argument The default value is[]
.:allow_nil?
- Whether or not the argument value may be nil (or may be not provided) The default value istrue
.:private?
- Whether or not the argument should be suppliable by the client. The default value isfalse
.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:default
- The default value for the argument to take. It can be a zero argument function e.g&MyMod.my_fun/0
or a value
prepare
Declares a preparation, which can be used to prepare a query for a read action.
Examples:
prepare build(sort: [:foo, :bar])
:preparation
- Required. The module and options for a preparation.
pagination
Adds pagination options to a resource
:keyset?
- Whether or not keyset based pagination is supported The default value isfalse
.:offset?
- Whether or not offset based pagination is supported The default value isfalse
.:default_limit
- The default page size to apply, if one is not supplied:countable
- Whether not a returned page will have a full count of all records. Use:by_default
to do it automatically. The default value isfalse
.:max_page_size
- The maximum amount of records that can be requested in a single page The default value is250
.:required?
- Whether or not pagination can be disabled. Only relevant if some pagination configuration is supplied. The default value istrue
.
update
update
Declares a update
action. For calling this action, see the Ash.Api
documentation.
Examples:
update :flag_for_review, primary?: true
:name
- Required. The name of the action:primary?
- Whether or not this action should be used when no action is specified by the caller. The default value isfalse
.:description
- An optional description for the action:transaction?
- Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default totrue
.
Has no effect if the data layer does not support transactions, or if that data layer is already in a transaction.:touches_resources
- A list of resources that the action may touch, used when building transactions.:accept
- The list of attributes to accept. Defaults to all attributes on the resource:reject
- A list of attributes not to accept. This is useful if you want to say 'accept all but x'
If this is specified along withaccept
, then everything in theaccept
list minus any matches in thereject
list will be accepted.:require_attributes
- A list of attributes that would normallyallow_nil?
, to require for this action.
No need to include attributes that already do not allow nil?:error_handler
- Sets the error handler on the changeset. SeeAsh.Changeset.handle_errors/2
for more:manual?
- Instructs Ash to skip the actual update/create/destroy step at the data layer. See the manual action guides for more.
change
A change to be applied to the changeset.
Examples:
change relate_actor(:reporter)
change {MyCustomChange, :foo}
:only_when_valid?
- If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here. The default value isfalse
.:description
- An optional description for the change:change
- Required. The module and options for a change.:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but instead just result in this change being ignored. The default value is[]
.
validate
Declares a validation to be applied to the changeset.
Examples:
validate changing(:email)
:validation
- Required. The module/opts pair of the validation:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but will instead result in this validation being ignored. The default value is[]
.:only_when_valid?
- If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data. The default value isfalse
.:message
- If provided, overrides any message set by the validation error:description
- An optional description for the validation:before_action?
- If set totrue
, the validation will be run in a before_action hook The default value isfalse
.
metadata
A special kind of attribute that is only added to specific actions. Nothing sets this value, it must be set in a custom
change via Ash.Resource.Info.put_metadata/3
.
Examples:
metadata :api_token, :string, allow_nil?: false
metadata :operation_id, :string, allow_nil?: false
:name
- Required. The name of the metadata:type
- Required. The type of the metadata:constraints
- Type constraints on the metadata The default value is[]
.:description
- An optional description for the metadata.:allow_nil?
- Whether or not the metadata may returnnil
The default value istrue
.:default
- The default value for the metadata to take. It can be a zero argument function e.g&MyMod.my_fun/0
or a value
argument
Declares an argument on the action
Examples:
argument :password_confirmation, :string
:name
- Required. The name of the argument:type
- Required. The type of the argument:description
- An optional description for the argument.:constraints
- Type constraints on the argument The default value is[]
.:allow_nil?
- Whether or not the argument value may be nil (or may be not provided) The default value istrue
.:private?
- Whether or not the argument should be suppliable by the client. The default value isfalse
.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:default
- The default value for the argument to take. It can be a zero argument function e.g&MyMod.my_fun/0
or a value
destroy
destroy
Declares a destroy
action. For calling this action, see the Ash.Api
documentation.
Examples:
destroy :soft_delete do
primary? true
end
:soft?
- If specified, the destroy action behaves as an update internally:name
- Required. The name of the action:primary?
- Whether or not this action should be used when no action is specified by the caller. The default value isfalse
.:description
- An optional description for the action:transaction?
- Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default totrue
.
Has no effect if the data layer does not support transactions, or if that data layer is already in a transaction.:touches_resources
- A list of resources that the action may touch, used when building transactions.:accept
- The list of attributes to accept. Defaults to all attributes on the resource:reject
- A list of attributes not to accept. This is useful if you want to say 'accept all but x'
If this is specified along withaccept
, then everything in theaccept
list minus any matches in thereject
list will be accepted.:require_attributes
- A list of attributes that would normallyallow_nil?
, to require for this action.
No need to include attributes that already do not allow nil?:error_handler
- Sets the error handler on the changeset. SeeAsh.Changeset.handle_errors/2
for more:manual?
- Instructs Ash to skip the actual update/create/destroy step at the data layer. See the manual action guides for more.
change
A change to be applied to the changeset.
Examples:
change relate_actor(:reporter)
change {MyCustomChange, :foo}
:only_when_valid?
- If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here. The default value isfalse
.:description
- An optional description for the change:change
- Required. The module and options for a change.:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but instead just result in this change being ignored. The default value is[]
.
validate
Declares a validation to be applied to the changeset.
Examples:
validate changing(:email)
:validation
- Required. The module/opts pair of the validation:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but will instead result in this validation being ignored. The default value is[]
.:only_when_valid?
- If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data. The default value isfalse
.:message
- If provided, overrides any message set by the validation error:description
- An optional description for the validation:before_action?
- If set totrue
, the validation will be run in a before_action hook The default value isfalse
.
metadata
A special kind of attribute that is only added to specific actions. Nothing sets this value, it must be set in a custom
change via Ash.Resource.Info.put_metadata/3
.
Examples:
metadata :api_token, :string, allow_nil?: false
metadata :operation_id, :string, allow_nil?: false
:name
- Required. The name of the metadata:type
- Required. The type of the metadata:constraints
- Type constraints on the metadata The default value is[]
.:description
- An optional description for the metadata.:allow_nil?
- Whether or not the metadata may returnnil
The default value istrue
.:default
- The default value for the metadata to take. It can be a zero argument function e.g&MyMod.my_fun/0
or a value
argument
Declares an argument on the action
Examples:
argument :password_confirmation, :string
:name
- Required. The name of the argument:type
- Required. The type of the argument:description
- An optional description for the argument.:constraints
- Type constraints on the argument The default value is[]
.:allow_nil?
- Whether or not the argument value may be nil (or may be not provided) The default value istrue
.:private?
- Whether or not the argument should be suppliable by the client. The default value isfalse
.:sensitive?
- Whether or not the attribute value contains sensitive information, like PII. The default value isfalse
.:default
- The default value for the argument to take. It can be a zero argument function e.g&MyMod.my_fun/0
or a value
code_interface
code_interface
Functions that will be defined on the Api module to interact with this resource.
Examples:
code_interface do
define_for MyApp.Api
define :create_user, action: :create
define :get_user_by_id, action: :get_by_id, args: [:id], get?: true
end
:define_for
- Defines the code interface on the resource module directly, using the provided Api. The default value isfalse
.
define
define
Defines a function on the Api with the corresponding name and arguments.
Examples:
define :get_user_by_id, action: :get_by_id, args: [:id], get?: true
:name
- Required. The name of the function that will be defined:action
- The name of the action that will be called. Defaults to the same name as the function.:args
- Map specific arguments to named inputs. Can provide any argument/attributes that the action allows.:get?
- Expects to only receive a single result from a read action, and returns a single result instead of a list. Ignored for other action types.:get_by
- Takes a list of fields and adds those fields as arguments, which will then be used to filter. Setsget?
to true automatically. Ignored for non-read actions.:get_by_identity
- Only relevant for read actions. Takes an identity, and gets its field list, performing the same logic asget_by
once it has the list of fields.
resource
resource
General Resource Configuration
Examples:
resource do
description "A description of this resource"
base_filter [is_nil: :deleted_at]
end
Imports:
:description
- A human readable description of the resource, to be used in generated documentation:base_filter
- A filter statement to be applied to any queries on the resource:default_context
- Default context to apply to any queries/changesets generated for this resource.:trace_name
- The name to use in traces. Defaults to the short_name stringified:short_name
- A short identifier for the resource, which should be unique.
identities
identities
Unique identifiers for the resource
Examples:
identities do
identity :full_name, [:first_name, :last_name]
identity :email, [:email]
end
identity
identity
Represents a unique constraint on the resource.
Examples:
identity :name, [:name]
identity :full_name, [:first_name, :last_name]
:name
- Required. The name of the identity.:keys
- Required. The names of the attributes that uniquely identify this resource.:eager_check_with
- Validates that the unique identity provided is unique at validation time, outside of any transactions, using the api module provided.:pre_check_with
- Validates that the unique identity provided is unique in a before_action hook.:description
- An optional description for the identity:message
- An error message to use when the unique identity would be violated
changes
changes
Declare changes that occur on create/update/destroy actions against the resource
Examples:
changes do
change {Mod, [foo: :bar]}
change set_context(%{some: :context})
end
Imports:
change
change
A change to be applied to the changeset.
Examples:
change relate_actor(:reporter)
change {MyCustomChange, :foo}
:on
- The action types the validation should run on. Destroy actions are omitted by default as most changes don't make sense for a destroy. The default value is[:create, :update]
.:only_when_valid?
- If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here. The default value isfalse
.:description
- An optional description for the change:change
- Required. The module and options for a change.:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but instead just result in this change being ignored. The default value is[]
.
preparations
preparations
Declare preparations that occur on all read actions for a given resource
Examples:
preparations do
prepare {Mod, [foo: :bar]}
prepare set_context(%{some: :context})
end
Imports:
prepare
prepare
Declares a preparation, which can be used to prepare a query for a read action.
Examples:
prepare build(sort: [:foo, :bar])
:preparation
- Required. The module and options for a preparation.
validations
validations
Declare validations prior to performing actions against the resource
Examples:
validations do
validate {Mod, [foo: :bar]}
validate at_least_one_of_present([:first_name, :last_name])
end
Imports:
validate
validate
Declares a validation for creates and updates.
Examples:
validate {Mod, [foo: :bar]}
validate at_least_one_of_present([:first_name, :last_name])
:validation
- Required. The module/opts pair of the validation:where
- Validations that should pass in order for this validation to apply. These validations failing will not invalidate the changes, but will instead result in this validation being ignored. The default value is[]
.:on
- The action types the validation should run on.
Many validations don't make sense in the context of deletion, so by default it is left out of the list. The default value is[:create, :update]
.:only_when_valid?
- If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data. The default value isfalse
.:message
- If provided, overrides any message set by the validation error:description
- An optional description for the validation:before_action?
- If set totrue
, the validation will be run in a before_action hook The default value isfalse
.
aggregates
aggregates
Declare named aggregates on the resource.
These are aggregates that can be loaded only by name using Ash.Query.load/2
.
They are also available as top level fields on the resource.
Examples:
aggregates do
count :assigned_ticket_count, :reported_tickets do
filter [active: true]
end
end
Imports:
count
count
Declares a named count aggregate on the resource
Supports filter
, but not sort
(because that wouldn't affect the count)
Examples:
count :assigned_ticket_count, :assigned_tickets do
filter [active: true]
end
:name
- Required. The field to place the aggregate in:relationship_path
- Required. The relationship or relationship path to use for the aggregate:kind
- Required. The kind of the aggregate:field
- The field to aggregate. Defaults to the first field in the primary key of the resource:filter
- A filter to apply to the aggregate The default value is[]
.:description
- An optional description for the aggregate:default
- A default value to use in cases where nil would be used. Count defaults to0
butfirst
andcount
do not have defaults.:private?
- Whether or not the aggregate will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:filterable?
- Whether or not the aggregate should be usable in filters. The default value istrue
.
first
first
Declares a named first
aggregate on the resource
First aggregates return the first value of the related record
that matches. Supports both filter
and sort
.
Examples:
first :first_assigned_ticket_subject, :assigned_tickets, :subject do
filter [active: true]
sort [:subject]
end
:name
- Required. The field to place the aggregate in:relationship_path
- Required. The relationship or relationship path to use for the aggregate:kind
- Required. The kind of the aggregate:field
- The field to aggregate. Defaults to the first field in the primary key of the resource:filter
- A filter to apply to the aggregate The default value is[]
.:sort
- A sort to be applied to the aggregate:description
- An optional description for the aggregate:default
- A default value to use in cases where nil would be used. Count defaults to0
butfirst
andcount
do not have defaults.:private?
- Whether or not the aggregate will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:filterable?
- Whether or not the aggregate should be usable in filters. The default value istrue
.
sum
sum
Declares a named sum
aggregate on the resource
Supports filter
, but not sort
(because that wouldn't affect the sum)
Examples:
sum :assigned_ticket_price_sum, :assigned_tickets, :price do
filter [active: true]
end
:name
- Required. The field to place the aggregate in:relationship_path
- Required. The relationship or relationship path to use for the aggregate:kind
- Required. The kind of the aggregate:field
- The field to aggregate. Defaults to the first field in the primary key of the resource:filter
- A filter to apply to the aggregate The default value is[]
.:description
- An optional description for the aggregate:default
- A default value to use in cases where nil would be used. Count defaults to0
butfirst
andcount
do not have defaults.:private?
- Whether or not the aggregate will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:filterable?
- Whether or not the aggregate should be usable in filters. The default value istrue
.
list
list
Declares a named list
aggregate on the resource.
A list aggregate simply selects the list of all values for the given field and relationship combination.
Examples:
list :assigned_ticket_prices, :assigned_tickets, :price do
filter [active: true]
end
:name
- Required. The field to place the aggregate in:relationship_path
- Required. The relationship or relationship path to use for the aggregate:kind
- Required. The kind of the aggregate:field
- The field to aggregate. Defaults to the first field in the primary key of the resource:filter
- A filter to apply to the aggregate The default value is[]
.:sort
- A sort to be applied to the aggregate:description
- An optional description for the aggregate:default
- A default value to use in cases where nil would be used. Count defaults to0
butfirst
andcount
do not have defaults.:private?
- Whether or not the aggregate will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:filterable?
- Whether or not the aggregate should be usable in filters. The default value istrue
.
calculations
calculations
Declare named calculations on the resource.
These are calculations that can be loaded only by name using Ash.Query.load/2
.
They are also available as top level fields on the resource.
- calculate
- argument
Examples:
calculations do
calculate :full_name, :string, MyApp.MyResource.FullName
end
Imports:
calculate
calculate
Declares a named calculation on the resource.
Takes a module that must adopt the Ash.Calculation
behaviour. See that module
for more information.
To ensure that the necessary fields are selected:
1.) Specifying the select
option on a calculation in the resource.
2.) Define a select/2
callback in the calculation module
3.) Set always_select?
on the attribute in question
Examples:
Ash.Calculation
implementation example:
calculate :full_name, :string, {MyApp.FullName, keys: [:first_name, :last_name]}, select: [:first_name, :last_name]
expr/1
example:
calculate :full_name, :string, expr(first_name <> " " <> last_name
:name
- Required. The field name to use for the calculation value:type
- Required. The type of the calculation:constraints
- Constraints to provide to the type. The default value is[]
.:allow_async?
- If set totrue
, then the calculation may be run after the main query. The default value isfalse
.:calculation
- Required. The module or{module, opts}
to use for the calculation:description
- An optional description for the calculation:private?
- Whether or not the calculation will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value isfalse
.:select
- A list of fields to ensure selected if the calculation is used. The default value is[]
.:load
- A load statement to be applied if the calculation is used. The default value is[]
.:allow_nil?
- Whether or not the calculation can return nil. The default value istrue
.:filterable?
- Whether or not the calculation should be usable in filters. The default value istrue
.
argument
An argument to be passed into the calculation's arguments map
Examples:
argument :params, :map do
default %{}
end
argument :retries, :integer do
allow_nil? false
end
:name
- Required. The name of the argument:type
- Required. The type of the argument:default
- A default value to use for the argument if not provided:allow_nil?
- Whether or not the argument value may be nil (or may be not provided) The default value istrue
.:constraints
- Constraints to provide to the type when casting the value. See the type's documentation for more information. The default value is[]
.
multitenancy
multitenancy
Options for configuring the multitenancy behavior of a resource.
To specify a tenant, use Ash.Query.set_tenant/2
or
Ash.Changeset.set_tenant/2
before passing it to an operation.
Examples:
multitenancy do
strategy :attribute
attribute :organization_id
global? true
end
:strategy
- Determine if multitenancy is performed with attribute filters or using data layer features. The default value is:context
.:attribute
- If using theattribute
strategy, the attribute to use, e.gorg_id
:global?
- Whether or not the data also exists outside of each tenant. The default value isfalse
.:parse_attribute
- An mfa ({module, function, args}) pointing to a function that takes a tenant and returns the attribute value The default value is{Ash.Resource.Dsl, :identity, []}
.