View Source Ash.Resource.Dsl (ash v1.53.0)

The built in resource DSL.

dsl-documentation

DSL Documentation

index

Index

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

attribute

attribute

Declares an attribute on the resource.

Introspection Target:

Ash.Resource.Attribute

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.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :source - If the field should be mapped to a different name in the data layer.

  • :always_select? - Whether or not to ensure this attribute is always selected when reading from the database. The default value is false.

  • :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 is false.

  • :allow_nil? - Whether or not the attribute can be set to nil. The default value is true.

  • :generated? - Whether or not the value may be generated by the data layer. The default value is false.

  • :writable? - Whether or not the value can be written to. The default value is true.

  • :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 is false.

  • :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 is true.

  • :default - A value to be set on all creates, unless a value is being provided already.

  • :description - An optional description for the attribute.

  • :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 unless default 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 is false.

create_timestamp

create_timestamp

Declares a non-writable attribute with a create default of &DateTime.utc_now/0

Introspection Target:

Ash.Resource.Attribute

Examples:

create_timestamp :inserted_at
  • :name - The name of the attribute.

  • :type - The type of the attribute. The default value is Ash.Type.UtcDatetimeUsec.

  • :constraints - Constraints to provide to the type when casting the value. See the type's documentation for more information.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :source - If the field should be mapped to a different name in the data layer.

  • :always_select? - Whether or not to ensure this attribute is always selected when reading from the database. The default value is false.

  • :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 is false.

  • :allow_nil? - Whether or not the attribute can be set to nil. The default value is false.

  • :generated? - Whether or not the value may be generated by the data layer. The default value is false.

  • :writable? - Whether or not the value can be written to. The default value is false.

  • :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 is true.

  • :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 is true.

  • :default - A value to be set on all creates, unless a value is being provided already. The default value is &DateTime.utc_now/0.

  • :description - An optional description for the attribute.

  • :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 unless default 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 is true.

update_timestamp

update_timestamp

Declares a non-writable attribute with a create and update default of &DateTime.utc_now/0

Introspection Target:

Ash.Resource.Attribute

Examples:

update_timestamp :inserted_at
  • :name - The name of the attribute.

  • :type - The type of the attribute. The default value is Ash.Type.UtcDatetimeUsec.

  • :constraints - Constraints to provide to the type when casting the value. See the type's documentation for more information.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :source - If the field should be mapped to a different name in the data layer.

  • :always_select? - Whether or not to ensure this attribute is always selected when reading from the database. The default value is false.

  • :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 is false.

  • :allow_nil? - Whether or not the attribute can be set to nil. The default value is false.

  • :generated? - Whether or not the value may be generated by the data layer. The default value is false.

  • :writable? - Whether or not the value can be written to. The default value is false.

  • :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 is true.

  • :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 is true.

  • :default - A value to be set on all creates, unless a value is being provided already. The default value is &DateTime.utc_now/0.

  • :description - An optional description for the attribute.

  • :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 unless default 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 is true.

timestamps

timestamps

Declares non-writable inserted_at and updated_at attributes with create and update defaults of &DateTime.utc_now/0.

Introspection Target:

Ash.Resource.Attribute

Examples:

timestamps()

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.

Introspection Target:

Ash.Resource.Attribute

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.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :source - If the field should be mapped to a different name in the data layer.

  • :always_select? - Whether or not to ensure this attribute is always selected when reading from the database. The default value is false.

  • :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 is true.

  • :generated? - Whether or not the value may be generated by the data layer. The default value is true.

  • :writable? - Whether or not the value can be written to. The default value is false.

  • :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 is false.

  • :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 is true.

  • :default - A value to be set on all creates, unless a value is being provided already.

  • :description - An optional description for the attribute.

  • :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 unless default 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 is false.

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.

Introspection Target:

Ash.Resource.Attribute

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.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :source - If the field should be mapped to a different name in the data layer.

  • :always_select? - Whether or not to ensure this attribute is always selected when reading from the database. The default value is false.

  • :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 is true.

  • :generated? - Whether or not the value may be generated by the data layer. The default value is false.

  • :writable? - Whether or not the value can be written to. The default value is false.

  • :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 is false.

  • :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 is true.

  • :default - A value to be set on all creates, unless a value is being provided already. The default value is &Ash.UUID.generate/0.

  • :description - An optional description for the attribute.

  • :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 unless default 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 is false.

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_field_on_join_table :category_id
    source_field_on_join_table :post_id
  end
end
relationships do
  has_many :posts, MyApp.Post do
    destination_field :author_id
  end

  has_many :composite_key_posts, MyApp.CompositeKeyPost do
    destination_field :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.

Introspection Target:

Ash.Resource.Relationships.HasOne

Examples:

# In a resource called `Word`
has_one :dictionary_entry, DictionaryEntry do
  source_field :text
  destination_field :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_fields? - If true, all existing entities are considered related, i.e this relationship is not based on any fields, and source_field and destination_field are ignored.
    This can be very useful when combined with multitenancy. Specifically, if you have a tenant resource like Organization, you can use no_fields? to do things like has_many :employees, Employee, no_fields?: true, which lets you avoid having an unnecessary organization_id field on Employee. The same works in reverse: has_one :organization, Organization, no_fields?: true allows relating the employee to their organization.
    Some important caveats here:

  1. 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.
  2. 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 load employees, 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.
  • :required? - Marks the relationship as required. This is not currently validated anywhere, since the relationship is managed by the destination, but ash_graphql uses it for type information, and it can be used for expressiveness.

  • :name - The name of the relationship

  • :destination - The destination resource

  • :destination_field - The field on the related resource that should match the source_field on this resource.

  • :validate_destination_field? - Whether or not to validate that the destination field exists on the destination resource The default value is true.

  • :source_field - The field on this resource that should match the destination_field on the related resource. The default value is :id.

  • :description - An optional description for the relationship

  • :relationship_context - Context to be set on any queries or changesets generated for this relationship.
    This is used by ash_postgres for polymorphic resources.

  • :private? - Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value is false.

  • :not_found_message - A message to show if there is a conflict with this relationship in the database on update or create.
    For example, if a value is added that has no match in the destination (very hard to do with the way Ash relationship changes work).

  • :writable? - Wether or not the relationship may be edited. The default value is true.

  • :read_action - The read action on the destination resource to use when loading data.
    Keep in mind, any filters that exist on the destination action are not honored when filtering on this relationship. The only time the read action comes into play is when loading the actual relationship, which happens when they are loaded explicitly and when the relationship is managed.

  • :api - The API module to use when working with the related entity.

  • :filter - A filter to be applied when reading the relationship.

  • :sort - A sort statement to be applied when reading the relationship.

  • :could_be_related_at_creation? - This toggle modifies the management of the relationship. Typically, on creation, the existing value of the relationship isn't loaded. However, if it is possible for things to be related before this record is created, for example if your data layers does not support primary keys, then you should set this to true. The default value is false.

  • :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.

Introspection Target:

Ash.Resource.Relationships.HasMany

Examples:

# In a resource called `Word`
has_many :definitions, DictionaryDefinition do
  source_field :text
  destination_field :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_fields? - If true, all existing entities are considered related, i.e this relationship is not based on any fields, and source_field and destination_field are ignored.
    This can be very useful when combined with multitenancy. Specifically, if you have a tenant resource like Organization, you can use no_fields? to do things like has_many :employees, Employee, no_fields?: true, which lets you avoid having an unnecessary organization_id field on Employee. The same works in reverse: has_one :organization, Organization, no_fields?: true allows relating the employee to their organization.
    Some important caveats here:

  1. 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.
  2. 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 load employees, 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

  • :destination_field - The field on the related resource that should match the source_field on this resource.

  • :validate_destination_field? - Whether or not to validate that the destination field exists on the destination resource The default value is true.

  • :source_field - The field on this resource that should match the destination_field on the related resource. The default value is :id.

  • :description - An optional description for the relationship

  • :relationship_context - Context to be set on any queries or changesets generated for this relationship.
    This is used by ash_postgres for polymorphic resources.

  • :private? - Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value is false.

  • :not_found_message - A message to show if there is a conflict with this relationship in the database on update or create.
    For example, if a value is added that has no match in the destination (very hard to do with the way Ash relationship changes work).

  • :writable? - Wether or not the relationship may be edited. The default value is true.

  • :read_action - The read action on the destination resource to use when loading data.
    Keep in mind, any filters that exist on the destination action are not honored when filtering on this relationship. The only time the read action comes into play is when loading the actual relationship, which happens when they are loaded explicitly and when the relationship is managed.

  • :api - The API module to use when working with the related entity.

  • :filter - A filter to be applied when reading the relationship.

  • :sort - A sort statement to be applied when reading the relationship.

  • :could_be_related_at_creation? - This toggle modifies the management of the relationship. Typically, on creation, the existing value of the relationship isn't loaded. However, if it is possible for things to be related before this record is created, for example if your data layers does not support primary keys, then you should set this to true. The default value is false.

  • :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 table.

A join table is typically a table who's primary key consists of one foreign key to each resource.

Introspection Target:

Ash.Resource.Relationships.ManyToMany

Examples:

# In a resource called `Word`
many_to_many :books, Book do
  through BookWord
  source_field :text
  source_field_on_join_table :word_text
  destination_field :id
  destination_field_on_join_table :book_id
end

# And in `BookWord` (the resource that defines the join table)
belongs_to :book, Book, primary_key?: true, required?: true
belongs_to :word, Word, primary_key?: true, required?: true
  • :source_field_on_join_table - Required. The field on the join table that should line up with source_field on this resource.

  • :destination_field_on_join_table - Required. The field on the join table that should line up with destination_field on the related resource.

  • :through - Required. The resource to use as the join resource.

  • :join_relationship - The has_many relationship to the join table. Defaults to <relationship_name>_join_assoc

  • :name - The name of the relationship

  • :destination - The destination resource

  • :destination_field - The field on the related resource that should match the source_field on this resource. The default value is :id.

  • :validate_destination_field? - Whether or not to validate that the destination field exists on the destination resource The default value is true.

  • :source_field - The field on this resource that should match the destination_field on the related resource. The default value is :id.

  • :description - An optional description for the relationship

  • :relationship_context - Context to be set on any queries or changesets generated for this relationship.
    This is used by ash_postgres for polymorphic resources.

  • :private? - Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value is false.

  • :not_found_message - A message to show if there is a conflict with this relationship in the database on update or create.
    For example, if a value is added that has no match in the destination (very hard to do with the way Ash relationship changes work).

  • :writable? - Wether or not the relationship may be edited. The default value is true.

  • :read_action - The read action on the destination resource to use when loading data.
    Keep in mind, any filters that exist on the destination action are not honored when filtering on this relationship. The only time the read action comes into play is when loading the actual relationship, which happens when they are loaded explicitly and when the relationship is managed.

  • :api - The API module to use when working with the related entity.

  • :filter - A filter to be applied when reading the relationship.

  • :sort - A sort statement to be applied when reading the relationship.

  • :could_be_related_at_creation? - This toggle modifies the management of the relationship. Typically, on creation, the existing value of the relationship isn't loaded. However, if it is possible for things to be related before this record is created, for example if your data layers does not support primary keys, then you should set this to true. The default value is false.

  • :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_field?: false is provided.

Introspection Target:

Ash.Resource.Relationships.BelongsTo

Examples:

# In a resource called `Word`
belongs_to :dictionary_entry, DictionaryEntry do
  source_field :text,
  destination_field :word_text
end
  • :primary_key? - Whether this field is, or is part of, the primary key of a resource. The default value is false.

  • :required? - Whether this relationship must always be present, e.g: must be included on creation, and never removed (it can still be changed) The default value is false.

  • :attribute_writable? - Whether this relationship's generated attribute will be marked as public & writable.
    Has no effect when combined with define_field?: false. The default value is false.

  • :define_field? - If set to false a field is not created on the resource for this relationship, and one must be manually added in attributes. The default value is true.

  • :field_type - The field type of the automatically created field. The default value is :uuid.

  • :name - The name of the relationship

  • :destination - The destination resource

  • :destination_field - The field on the related resource that should match the source_field on this resource. The default value is :id.

  • :validate_destination_field? - Whether or not to validate that the destination field exists on the destination resource The default value is true.

  • :source_field - The field on this resource that should match the destination_field on the related resource. - Defaults to <name>_id

  • :description - An optional description for the relationship

  • :relationship_context - Context to be set on any queries or changesets generated for this relationship.
    This is used by ash_postgres for polymorphic resources.

  • :private? - Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql The default value is false.

  • :not_found_message - A message to show if there is a conflict with this relationship in the database on update or create.
    For example, if a value is added that has no match in the destination (very hard to do with the way Ash relationship changes work).

  • :writable? - Wether or not the relationship may be edited. The default value is true.

  • :read_action - The read action on the destination resource to use when loading data.
    Keep in mind, any filters that exist on the destination action are not honored when filtering on this relationship. The only time the read action comes into play is when loading the actual relationship, which happens when they are loaded explicitly and when the relationship is managed.

  • :api - The API module to use when working with the related entity.

  • :filter - A filter to be applied when reading the relationship.

  • :sort - A sort statement to be applied when reading 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
  • 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:


  • :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

create

create

Declares a create action. For calling this action, see the Ash.Api documentation.

Introspection Target:

Ash.Resource.Actions.Create

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, but this allows for setting required attributes in your changes under the hood.

  • :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 is false.

  • :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 to true.
    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.
    If your action has custom code (i.e custom changes) that touch resources that use a different data layer, this can be used to inform the transaction logic that these resource's data layer's should be involved in the transaction. In most standard set ups, this should not be necessary.

  • :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 with accept, then everything in the accept list minus any matches in the reject list will be accepted.

  • :require_attributes - A list of attributes that would normally allow_nil to require for this action.
    No need to include attributes that are allow_nil?: false.

  • :error_handler - Sets the error handler on the changeset. See Ash.Changeset.handle_errors/2 for more

  • :manual? - Instructs Ash to skip the actual update/create/destroy step.
    All validation still takes place, but the result in any after_action callbacks attached to that action will simply be the record that was read from the database initially. For creates, the result will be nil, and you will be expected to handle the changeset in an after_action callback and return an instance of the record. This is a good way to prevent Ash from issuing an unnecessary update to the record, e.g updating the updated_at of the record when an action actually only involves modifying relating records.
    You could then handle the changeset automatically.
    For example:

in the action

action :special_create do
  manual? true
  change MyApp.DoCreate
end  
# The change
defmodule MyApp.DoCreate do
  use Ash.Resource.Change  
  def change(changeset, _, _) do
    Ash.Changeset.after_action(changeset, fn changeset, _result ->
      # result will be `nil`, because this is a manual action  
      result = do_something_that_creates_the_record(changeset)  
      {:ok, result}
    end)
  end
end
change

A change to be applied to the changeset after it is generated. They are run in order, from top to bottom.

To implement your own, see Ash.Resource.Change. To use it, simply refer to the module and its options or just the module if there are no options, like so:

change {MyChange, foo: 1} change MyChange

Introspection Target:

Ash.Resource.Change

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.
    For 2.0 this may become the default. The default value is false.

  • :change - Required. The module and options for a change.

  • :where - false 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 for the current action

Introspection Target:

Ash.Resource.Validation

Examples:

validate changing(:email)
  • :validation - Required. The module/opts pair of the validation

  • :where - false 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 validation being ignored. The default value is [].

  • :expensive? - If a validation is expensive, it won't be run on invalid changes. All inexpensive validations are always run, to provide informative errors. The default value is false.

  • :message - If provided, overrides any message set by the validation error

  • :description - An optional description for the validation

  • :before_action? - If set to true, the validation is not run when building changesets using Ash.Changeset.for_*. The validation will only ever be run once the action itself is called. The default value is false.

argument

Declares an argument on the action

Introspection Target:

Ash.Resource.Actions.Argument

Examples:

argument :password_confirmation, :string
  • :allow_nil? - Whether or not the argument may be ommitted or set to nil The default value is true.

  • :type - Required. The type of the argument

  • :name - Required. The name of the argument

  • :private? - Whether or not the argument should be part of the public API The default value is false.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :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

  • :constraints - Type constraints on the argument The default value is [].

  • :description - An optional description for the argument.

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.

Introspection Target:

Ash.Resource.Actions.Metadata

Examples:

metadata :api_token, :string, allow_nil?: false
metadata :operation_id, :string, allow_nil?: false
  • :allow_nil? - Whether or not the metadata may return nil The default value is true.

  • :type - Required. The type of the metadata

  • :name - Required. The name of the metadata

  • :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

  • :constraints - Type constraints on the metadata The default value is [].

  • :description - An optional description for the metadata.

read

read

Declares a read action. For calling this action, see the Ash.Api documentation.

pagination

Pagination

  • :keyset? - Whether or not keyset based pagination is supported The default value is false.

  • :offset? - Whether or not offset based pagination is supported The default value is false.

  • :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 is false.

  • :max_page_size - The maximum amount of records that can be requested in a single page The default value is 250.

  • :required? - Whether or not pagination can be disabled. Only relevant if some pagination configuration is supplied. The default value is true.

  • argument

  • prepare

Introspection Target:

Ash.Resource.Actions.Read

Examples:

read :read_all do
  primary? true
end
  • :filter - A filter template, that may contain actor references. See Ash.Filter for more on templates

  • :manual - Allows for read actions that are fetched manually. WARNING: EXPERIMENTAL
    Manual read actions will simply be handed the ash query and the data layer query. If you simply want to customize/intercept the query before it is sent to the data layer then use modify_query instead. Using them in conjunction can help ensure that calculations and aggregates are all correct. For example, you could modify the query to alter/replace the where clause/filter using modify_query which will affect which records calculations are returned for. Then you can customize how it is run using manual.

    # in the resource
    actions do
      read :action_name do
        manual MyApp.ManualRead
        # or `{MyApp.ManualRead, ...opts}`
      end
    end  
    # the implementation
    defmodule MyApp.ManualRead do
      use Ash.Resource.ManualRead  
      def read(ash_query, ecto_query, _opts, _context) do
        ...
        {:ok, query_results} | {:error, error}
      end
    end
  • :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. This is not used internally (but may be in the future). The default value is false.

  • :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}.
    This is an experimental option, so if you use it you should be sure to test it under various scenarios, like usage in aggregates/calculations and loading from relationships.

  • :pagination - Options for how the action should support pagination. See the pagination section for more information. The default value is false.

  • :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 is false.

  • :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 to true.
    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.
    If your action has custom code (i.e custom changes) that touch resources that use a different data layer, this can be used to inform the transaction logic that these resource's data layer's should be involved in the transaction. In most standard set ups, this should not be necessary.

argument

Declares an argument on the action

Introspection Target:

Ash.Resource.Actions.Argument

Examples:

argument :password_confirmation, :string
  • :allow_nil? - Whether or not the argument may be ommitted or set to nil The default value is true.

  • :type - Required. The type of the argument

  • :name - Required. The name of the argument

  • :private? - Whether or not the argument should be part of the public API The default value is false.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :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

  • :constraints - Type constraints on the argument The default value is [].

  • :description - An optional description for the argument.

prepare

Declares a preparation, which can be used to prepare a query for a read action.

Introspection Target:

Ash.Resource.Preparation

Examples:

prepare build(sort: [:foo, :bar])
  • :preparation - Required. The module and options for a preparation.

update

update

Declares a update action. For calling this action, see the Ash.Api documentation.

Introspection Target:

Ash.Resource.Actions.Update

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 is false.

  • :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 to true.
    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.
    If your action has custom code (i.e custom changes) that touch resources that use a different data layer, this can be used to inform the transaction logic that these resource's data layer's should be involved in the transaction. In most standard set ups, this should not be necessary.

  • :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 with accept, then everything in the accept list minus any matches in the reject list will be accepted.

  • :require_attributes - A list of attributes that would normally allow_nil to require for this action.
    No need to include attributes that are allow_nil?: false.

  • :error_handler - Sets the error handler on the changeset. See Ash.Changeset.handle_errors/2 for more

  • :manual? - Instructs Ash to skip the actual update/create/destroy step.
    All validation still takes place, but the result in any after_action callbacks attached to that action will simply be the record that was read from the database initially. For creates, the result will be nil, and you will be expected to handle the changeset in an after_action callback and return an instance of the record. This is a good way to prevent Ash from issuing an unnecessary update to the record, e.g updating the updated_at of the record when an action actually only involves modifying relating records.
    You could then handle the changeset automatically.
    For example:

in the action

action :special_create do
  manual? true
  change MyApp.DoCreate
end  
# The change
defmodule MyApp.DoCreate do
  use Ash.Resource.Change  
  def change(changeset, _, _) do
    Ash.Changeset.after_action(changeset, fn changeset, _result ->
      # result will be `nil`, because this is a manual action  
      result = do_something_that_creates_the_record(changeset)  
      {:ok, result}
    end)
  end
end
change

A change to be applied to the changeset after it is generated. They are run in order, from top to bottom.

To implement your own, see Ash.Resource.Change. To use it, simply refer to the module and its options or just the module if there are no options, like so:

change {MyChange, foo: 1} change MyChange

Introspection Target:

Ash.Resource.Change

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.
    For 2.0 this may become the default. The default value is false.

  • :change - Required. The module and options for a change.

  • :where - false 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 for the current action

Introspection Target:

Ash.Resource.Validation

Examples:

validate changing(:email)
  • :validation - Required. The module/opts pair of the validation

  • :where - false 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 validation being ignored. The default value is [].

  • :expensive? - If a validation is expensive, it won't be run on invalid changes. All inexpensive validations are always run, to provide informative errors. The default value is false.

  • :message - If provided, overrides any message set by the validation error

  • :description - An optional description for the validation

  • :before_action? - If set to true, the validation is not run when building changesets using Ash.Changeset.for_*. The validation will only ever be run once the action itself is called. The default value is false.

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.

Introspection Target:

Ash.Resource.Actions.Metadata

Examples:

metadata :api_token, :string, allow_nil?: false
metadata :operation_id, :string, allow_nil?: false
  • :allow_nil? - Whether or not the metadata may return nil The default value is true.

  • :type - Required. The type of the metadata

  • :name - Required. The name of the metadata

  • :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

  • :constraints - Type constraints on the metadata The default value is [].

  • :description - An optional description for the metadata.

argument

Declares an argument on the action

Introspection Target:

Ash.Resource.Actions.Argument

Examples:

argument :password_confirmation, :string
  • :allow_nil? - Whether or not the argument may be ommitted or set to nil The default value is true.

  • :type - Required. The type of the argument

  • :name - Required. The name of the argument

  • :private? - Whether or not the argument should be part of the public API The default value is false.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :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

  • :constraints - Type constraints on the argument The default value is [].

  • :description - An optional description for the argument.

destroy

destroy

Declares a destroy action. For calling this action, see the Ash.Api documentation.

Introspection Target:

Ash.Resource.Actions.Destroy

Examples:

destroy :soft_delete do
  primary? true
end
  • :soft? - If specified, the destroy action calls the datalayer's update function with any specified changes.

  • :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 is false.

  • :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 to true.
    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.
    If your action has custom code (i.e custom changes) that touch resources that use a different data layer, this can be used to inform the transaction logic that these resource's data layer's should be involved in the transaction. In most standard set ups, this should not be necessary.

  • :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 with accept, then everything in the accept list minus any matches in the reject list will be accepted.

  • :require_attributes - A list of attributes that would normally allow_nil to require for this action.
    No need to include attributes that are allow_nil?: false.

  • :error_handler - Sets the error handler on the changeset. See Ash.Changeset.handle_errors/2 for more

  • :manual? - Instructs Ash to skip the actual update/create/destroy step.
    All validation still takes place, but the result in any after_action callbacks attached to that action will simply be the record that was read from the database initially. For creates, the result will be nil, and you will be expected to handle the changeset in an after_action callback and return an instance of the record. This is a good way to prevent Ash from issuing an unnecessary update to the record, e.g updating the updated_at of the record when an action actually only involves modifying relating records.
    You could then handle the changeset automatically.
    For example:

in the action

action :special_create do
  manual? true
  change MyApp.DoCreate
end  
# The change
defmodule MyApp.DoCreate do
  use Ash.Resource.Change  
  def change(changeset, _, _) do
    Ash.Changeset.after_action(changeset, fn changeset, _result ->
      # result will be `nil`, because this is a manual action  
      result = do_something_that_creates_the_record(changeset)  
      {:ok, result}
    end)
  end
end
change

A change to be applied to the changeset after it is generated. They are run in order, from top to bottom.

To implement your own, see Ash.Resource.Change. To use it, simply refer to the module and its options or just the module if there are no options, like so:

change {MyChange, foo: 1} change MyChange

Introspection Target:

Ash.Resource.Change

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.
    For 2.0 this may become the default. The default value is false.

  • :change - Required. The module and options for a change.

  • :where - false 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 for the current action

Introspection Target:

Ash.Resource.Validation

Examples:

validate changing(:email)
  • :validation - Required. The module/opts pair of the validation

  • :where - false 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 validation being ignored. The default value is [].

  • :expensive? - If a validation is expensive, it won't be run on invalid changes. All inexpensive validations are always run, to provide informative errors. The default value is false.

  • :message - If provided, overrides any message set by the validation error

  • :description - An optional description for the validation

  • :before_action? - If set to true, the validation is not run when building changesets using Ash.Changeset.for_*. The validation will only ever be run once the action itself is called. The default value is false.

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.

Introspection Target:

Ash.Resource.Actions.Metadata

Examples:

metadata :api_token, :string, allow_nil?: false
metadata :operation_id, :string, allow_nil?: false
  • :allow_nil? - Whether or not the metadata may return nil The default value is true.

  • :type - Required. The type of the metadata

  • :name - Required. The name of the metadata

  • :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

  • :constraints - Type constraints on the metadata The default value is [].

  • :description - An optional description for the metadata.

argument

Declares an argument on the action

Introspection Target:

Ash.Resource.Actions.Argument

Examples:

argument :password_confirmation, :string
  • :allow_nil? - Whether or not the argument may be ommitted or set to nil The default value is true.

  • :type - Required. The type of the argument

  • :name - Required. The name of the argument

  • :private? - Whether or not the argument should be part of the public API The default value is false.

  • :sensitive? - Whether or not the attribute value contains sensitive information, like PII. The default value is false.

  • :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

  • :constraints - Type constraints on the argument The default value is [].

  • :description - An optional description for the argument.

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 is false.

define

define

Defines a function on the Api with the corresponding name and arguments.

If the action is an update or destroy, it will take a record or a changeset as its first argument. If the action is a read action, it will take a starting query as an opt in the last argument.

All functions will have an optional last argument that accepts options. Those options are:

  • :tenant - set the tenant of the query/changeset

  • :context - set context on the query/changeset

  • :actor - set the actor for authorization

  • :authorize? - whether or not to perform authorization. If an actor option is provided (even if it is nil), defaults to true. If not, defaults to false.

  • :verbose? - a flag to toggle verbose output from the internal Ash engine (for debugging)

  • :timeout - A timeout to apply to the operation. See the timeouts guide for more.

For reads:

  • :query - a query to start the action with, can be used to filter/sort the results of the action.

For creates:

  • :changeset - a changeset to start the action with

They will also have an optional second to last argument that is a freeform map to provide action input. It must be a map. If it is a keyword list, it will be assumed that it is actually options (for convenience). This allows for the following behaviour:

# Because the 3rd argument is a keyword list, we use it as options
Api.register_user(username, password, [tenant: "organization_22"])
# Because the 3rd argument is a keyword list, we use it as action input
Api.register_user(username, password, %{key: "val"})
# When all are provided it is unambiguous
Api.register_user(username, password, %{key: "val"}, [tenant: "organization_22"])

Introspection Target:

Ash.Resource.Interface

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? - Only relevant for read actions. Expects to only receive a single result from a read action.
    The action should return a single result based on any arguments provided. To make it so that the function takes a specific field, and filters on that field, use get_by instead.
    Useful for creating functions like get_user_by_email that map to an action that has an :email argument.

  • :get_by - Only relevant for read actions. Takes a list of fields and adds those fields as arguments, which will then be used to filter.
    Automatically sets get? to true.
    The action should return a single result based on any arguments provided. To make it so that the function takes a specific field, and filters on that field, use get_by instead. When combined, get_by takes precedence.
    Useful for creating functions like get_user_by_id that map to a basic read action.

  • :get_by_identity - Only relevant for read actions. Takes an identity, and gets its field list, performing the same logic as get_by once it has the list of fields.

resource

resource

Resource-wide 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.

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.

Used for indicating that some set of attributes, calculations or aggregates uniquely identify a resource.

This will allow these fields to be passed to Ash.Api.get/3, e.g get(Resource, [some_field: 10]), if all of the keys are filterable. Otherwise they are purely descriptive at the moment. The primary key of the resource does not need to be listed as an identity.

Introspection Target:

Ash.Resource.Identity

Examples:

identity :name, [:name]
identity :full_name, [:first_name, :last_name]
  • :name - Required. The name of the identity. Used by extensions to target specific identities for fetching single instances of a resource

  • :keys - Required. The names of attributes, aggregates or calculations that uniquely identify this resource.

  • :eager_check_with - Validates that the unique identity provided is unique at validation time, using the api module provided.
    The identity is checked on each validation of the changeset. For example, if you are using AshPhoenix.Form, this looks for a conflicting record on each call to Form.validate/2. For updates, it is only checked if one of the involved fields is being changed.
    For creates, The identity is checked unless your are performing an upsert, and the upsert_identity is this identity. Keep in mind that for this to work properly, you will need to pass the upsert?: true, upsert_identity: :identity_name when creating the changeset instead of passing it to the Api when creating.
    The primary? action is used to search for a record. This will error if you have not configured one.

  • :pre_check_with - Validates that the unique identity provided is unique just prior to enacting the resource action, using the Api provided.
    Behaves the same as eager_check_with, but it runs just prior to the action being committed. Useful for data layers that don't support transactions/unique constraints, or manual resources with identities.

  • :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 after it is generated. They are run in order, from top to bottom.

To implement your own, see Ash.Resource.Change. To use it, simply refer to the module and its options or just the module if there are no options, like so:

change {MyChange, foo: 1} change MyChange

Introspection Target:

Ash.Resource.Change

Examples:

change relate_actor(:reporter)
change {MyCustomChange, :foo}
  • :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 change should only be run on valid changes. By default, all changes are run unless stated otherwise here.
    For 2.0 this may become the default. The default value is false.

  • :change - Required. The module and options for a change.

  • :where - false 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.

Introspection Target:

Ash.Resource.Preparation

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.

Introspection Target:

Ash.Resource.Validation

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 - false 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 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].

  • :expensive? - If a validation is expensive, it won't be run on invalid changes. All inexpensive validations are always run, to provide informative errors. The default value is false.

  • :message - If provided, overrides any message set by the validation error

  • :description - An optional description for the validation

  • :before_action? - If set to true, the validation is not run when building changesets using Ash.Changeset.for_*. The validation will only ever be run once the action itself is called. The default value is false.

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)

Introspection Target:

Ash.Resource.Aggregate

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 - false 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 to 0 but first and count 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 is false.

  • :filterable? - Whether or not the aggregate should be usable in filters. The default value is true.

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.

Introspection Target:

Ash.Resource.Aggregate

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 - false 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 to 0 but first and count 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 is false.

  • :filterable? - Whether or not the aggregate should be usable in filters. The default value is true.

sum

sum

Declares a named sum aggregate on the resource

Supports filter, but not sort (because that wouldn't affect the sum)

Introspection Target:

Ash.Resource.Aggregate

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 - false 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 to 0 but first and count 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 is false.

  • :filterable? - Whether or not the aggregate should be usable in filters. The default value is true.

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.

Introspection Target:

Ash.Resource.Aggregate

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 - false 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 to 0 but first and count 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 is false.

  • :filterable? - Whether or not the aggregate should be usable in filters. The default value is true.

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.

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

Introspection Target:

Ash.Resource.Calculation

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.

  • :constraints - Constraints to provide to the type. The default value is [].

  • :allow_async? - If set to true, then the calculation may be run after the main query.
    This is useful for calculations that are very expensive, especially when combined with complex filters/join scenarios. By adding this, we will rerun a trimmed down version of the main query, using the primary keys for fast access. This will be done asynchronously for each calculation that has allow_async?: true.
    Keep in mind that if the calculation is used in a filter or sort, it cannot be done asynchrnously, and must be done in the main query. The default value is false.

  • :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 is false.

  • :select - A list of fields to ensure selected in the case that the calculation is run. 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 is true.

  • :filterable? - Whether or not the calculation should be usable in filters. The default value is true.

argument

An argument to be passed into the calculation's arguments map

Introspection Target:

Ash.Resource.Calculation.Argument

Examples:

argument :params, :map do
  default %{}
end
argument :retries, :integer do
  allow_nil? false
end
  • :name - Required. The name to use for the argument

  • :type - Required. The type of the argument

  • :default - false A default value to use for the argument if not provided

  • :allow_nil? - Whether or not the argument value may be nil The default value is true.

  • :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 how to perform multitenancy. :attribute will expect that an attribute matches the given tenant, e.g org_id. context (the default) implies that the tenant will be passed to the datalayer as context. How a given data layer handles multitenancy will differ depending on the implementation. See the datalayer documentation for more. The default value is :context.

  • :attribute - If using the attribute strategy, the attribute to use, e.g org_id

  • :global? - Whether or not the data also exists outside of each tenant. This allows running queries and making changes without setting a tenant. This may eventually be extended to support describing the relationship to global data. For example, perhaps the global data is shared among all tenants (requiring "union" support in data layers), or perhaps global data is "merged" using some strategy (also requiring "union" support). The default value is false.

  • :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, []}.