Skip to main content
Glama

Gemini Docs MCP Server

by M-Gonzalo
ash.md2.04 MB
[![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Actions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/actions/actions.md#L1 "View Source") In Ash, actions are the primary way to interact with your resources. There are five types of actions: - [Read](read-actions.html) - [Create](create-actions.html) - [Update](update-actions.html) - [Destroy](destroy-actions.html) - [Generic](generic-actions.html) All actions can be run in a transaction. Create, update and destroy actions are run in a transaction by *default*, whereas read and generic actions require opting in with `transaction? true` in the action definition. Each action has its own set of options, ways of calling it, and ways of customizing it. See the relevant guide for specifics on each action type. This topic focuses on idiomatic ways to use actions, and concepts that cross all action types. ## [](actions.html#primary-actions)Primary Actions Primary actions are a way to inform the framework which actions should be used in certain "automated" circumstances, or in cases where an action has not been specified. If a primary action is attempted to be used but does not exist, you will get an error about it at runtime. The place you typically need primary actions is when [Managing Relationships](relationships.html#managing-relationships). When using the `defaults` option to add default actions, they are marked as primary. A simple example where a primary action would be used: ``` # No action is specified, so we look for a primary read. Ash.get!(Resource, "8ba0ab56-c6e3-4ab0-9c9c-df70e9945281") ``` To mark an action as primary, add the option, i.e ``` read :action_name do primary? true end ``` ## [](actions.html#accepting-inputs)Accepting Inputs [Create](create-actions.html) and [Update](update-actions.html) actions can accept attributes as input. There are two primary ways that you annotate this. ### [](actions.html#using-accept-in-specific-actions)Using `accept` in specific actions Each action can define what it accepts, for example: ``` create :create do accept [:name, :description] end ``` You could then pass in `%{name: "a name", description: "a description"}` to this action. ### [](actions.html#using-default_accept-for-all-actions)Using `default_accept` for all actions The resource can have a `default_accept`, declared in its `actions` block, which will be used as the accept list for `create` and `update` actions, if they don't define one. ``` actions do default_accept [:name, :description] create :create update :update update :special_update do accept [:something_else] end end ``` In the example above, you can provide `%{name: "a name", description: "a description"}` to both the `:create` and `:update` actions, but only `%{something_else: "some_value"}` to `:special_update`. ## [](actions.html#idiomatic-actions)Idiomatic Actions ### [](actions.html#name-your-actions)Name Your Actions The intent behind Ash is *not* to have you building simple CRUD style applications. In a typical set up you may have a resource with four basic actions, there is even a shorthand to accomplish this: ``` actions do defaults [:read, :destroy, create: :*, update: :*] end ``` But that is just a simple way to get started, or to create resources that really don't do anything beyond those four operations. You can have *as many actions as you want*. The best designed Ash applications will have numerous actions, named after the intent behind how they are used. They won't have all reads going through a single read action, and the same goes for the other action types. The richer the actions on the resource, the better interface you can have. With that said, many resources may only have those four basic actions, especially those that are "managed" through some parent resource. See the guide on [Managing Relationships](relationships.html#managing-relationships) for more. ### [](actions.html#put-everything-inside-the-action)Put everything inside the action Ash provides utilities to modify queries and changesets *outside* of the actions on the resources. This is a very important tool in our tool belt, *but* it is very easy to abuse. The intent is that as much behavior as possible is put into the action. Here is the "wrong way" to do it. There is a lot going on here, so don't hesitate to check out other relevant guides if you see something you don't understand. ``` def top_tickets(user_id) do Ticket |> Ash.Query.for_read(:read) |> Ash.Query.filter(priority in [:medium, :high]) |> Ash.Query.filter(representative_id == ^user_id) |> Ash.Query.filter(status == :open) |> Ash.Query.sort(opened_at: :desc) |> Ash.Query.limit(10) |> Helpdesk.Support.read!() end # in the resource actions do defaults [:read, ...] end ``` And here is the "right way", where the rules about getting the top tickets have been moved into the resource as a nicely named action, and included in the `code_interface` of that resource. The reality of the situation is that `top_tickets/1` is meant to be obsoleted by your Ash resource! Here is how it *should* be done. ``` # in the resource code_interface do define :top, args: [:user_id] end actions do read :top do argument :user_id, :uuid do allow_nil? false end prepare build(limit: 10, sort: [opened_at: :desc]) filter expr(priority in [:medium, :high] and representative_id == ^arg(:user_id) and status == :open) end end ``` Now, whatever code I had that would have called `top_tickets/1` can now call `Helpdesk.Support.Ticket.top(user.id)`. By doing it this way, you get the primary benefit of getting a nice simple interface to call into, but you *also* have a way to modify how the action is invoked in any way necessary, by going back to the old way of building the query manually. For example, if I also only want to see top tickets that were opened in the last 10 minutes: ``` Ticket |> Ash.Query.for_read(:top, %{user_id: user.id}) |> Ash.Query.filter(opened_at > ago(10, :minute)) |> Helpdesk.Support.read!() ``` That is the best of both worlds! These same lessons transfer to changeset based actions as well. ## [](actions.html#private-inputs)Private Inputs The concept of a "private input" can be somewhat paradoxical, but it can be used by actions that require something provided by the "system", as well as something provided by the caller. For example, you may want an `ip_address` input that can't be set by the user. For this, you have two options. ### [](actions.html#private-options)Private Options ``` create :create do argument :ip_address, :string, allow_nil?: false ... end ``` ``` Ash.Changeset.for_create(Resource, :create, %{}, private_arguments: %{ip_address: "<ip_address>"}) ``` ### [](actions.html#context)Context You can also provide things to the action via `context`. Context is a map that is a free form map provided to the action. Context is occasionally used by callers to provide additional information that the action may or may not use. Context is *deep merged* with any existing context, and also contains a `private` key that is reserved for use by Ash internals. You should not remove or manipulate the `private` context key in any way. ``` create :create do ... change fn changeset, _ -> changeset.context # %{ip_address: "<ip_address>"} end end ``` ``` Ash.Changeset.for_create(Resource, :create, %{}, context: %{ip_address: "<ip_address>"}) ``` [← Previous Page Notifiers](notifiers.html) [Next Page → Read Actions](read-actions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/actions/actions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Actors &amp; Authorization [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/security/actors-and-authorization.md#L1 "View Source") Authorization in Ash involves three things: - actor - the entity (i.e user, organization, device) performing a given action - authorize? - a flag that tells Ash to run authorization. - authorizers - the extensions on a resource that can modify or forbid the action. ## [](actors-and-authorization.html#setting-actor-and-authorize)Setting `actor` and `authorize?` All functions in Ash that may perform authorization and/or wish to use the actor accept an `actor` and an `authorize?` option. For example: Building a changeset/query/input is the best time to provide the actor option ``` Ash.Changeset.for_create(Post, %{title: "Post Title"}, actor: current_user, authorize?: true) ``` If calling a function without changeset/query/input, you can provide the `actor` option at that point. ``` Ash.count!(Post, actor: current_user, authorize?: true) ``` Functions created with the code interface also accept an `actor` option. ``` MyDomain.create_post!(Post, authorize?: true) ``` ### [](actors-and-authorization.html#set-the-actor-on-the-query-changeset-input)Set the actor on the query/changeset/input The hooks on a query/changeset/input to an action may need to know the actor, so you need to set the actor when building them, not when calling the action. ``` # DO THIS Post |> Ash.Query.for_read(:read, %{}, actor: current_user) |> Ash.read!() # DON'T DO THIS Post |> Ash.Query.for_read!(:read) |> Ash.read!(actor: current_user) ``` ## [](actors-and-authorization.html#default-value-of-authorize)Default value of `authorize?` The default value of `authorize?` is determined by the `authorization` configuration of the relevant domain. By default, `authorize?` is set to `true` (and so can be ommitted in all of the examples above). If a resource has no authorizers, then all requests will be allowed. ## [](actors-and-authorization.html#authorizers)Authorizers Authorizers are in control of what happens during authorization. Generally, you won't need to create your own authorizer, as the builtin policy authorizer [`Ash.Policy.Authorizer`](Ash.Policy.Authorizer.html) works well for any use case. See the [Policies guide](policies.html) for more. ## [](actors-and-authorization.html#domain-authorization-configuration)Domain Authorization Configuration ### [](actors-and-authorization.html#d-ash-domain-dsl-authorization-require_actor)`Ash.Domain.Dsl.authorization.require_actor?` Requires that an actor is set for all requests. Important: `nil` is still a valid actor, so this won't prevent providing `actor: nil`. It only requires that the option itself is provided. ### [](actors-and-authorization.html#d-ash-domain-dsl-authorization-authorize)`Ash.Domain.Dsl.authorization.authorize` When to run authorization for a given request. - `:by_default` sets `authorize?: true` if the `authorize?` option was not set (so it can be set to `false`). This is the default. - `:always` forces `authorize?: true` on all requests to the domain. - `:when_requested` sets `authorize?: true` whenever an actor is set or `authorize?: true` is explicitly passed. [← Previous Page Manual Actions](manual-actions.html) [Next Page → Sensitive Data](sensitive-data.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/security/actors-and-authorization.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Aggregates [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/aggregates.md#L1 "View Source") Aggregates in Ash allow for retrieving summary information over groups of related data. A simple example might be to show the "count of published posts for a user". Aggregates allow us quick and performant access to this data, in a way that supports being filtered/sorted on automatically. More aggregate types can be added, but you will be restricted to only the supported types. In cases where aggregates don't suffice, use [Calculations](calculations.html), which are intended to be much more flexible. ## [](aggregates.html#declaring-aggregates-on-a-resource)Declaring aggregates on a resource Aggregates are defined in an `aggregates` section. For all possible types, see below. For a full reference, see `Ash.Resource.Dsl.aggregates`. ``` aggregates do count :count_of_posts, :posts do filter expr(published == true) end end ``` ## [](aggregates.html#using-an-aggregate)Using an aggregate Aggregates are loaded and filtered on in the same way that calculations are. Lets look at some examples: ### [](aggregates.html#loading-aggregates-in-a-query-or-on-records)Loading aggregates in a query or on records ``` User |> Ash.Query.load(:count_of_posts) |> Map.get(:count_of_posts) # => 10 users |> Ash.load!(:count_of_posts) |> Enum.map(&(&1.count_of_posts) # => [3, 5, 2] ``` ### [](aggregates.html#filtering-on-aggregates)Filtering on aggregates ``` require Ash.Query User |> Ash.Query.filter(count_of_posts > 10) |> Ash.read!() ``` ### [](aggregates.html#sorting-aggregates)Sorting aggregates ``` User |> Ash.Query.sort(count_of_posts: :asc) |> Ash.read!() ``` ## [](aggregates.html#aggregate-types)Aggregate types - `count` - counts related items meeting the criteria. - `exists` - checks if any related items meet the criteria. - `first` - gets the first related value matching the criteria. Must specify the `field`. - `sum` - sums the related items meeting the criteria. Must specify the `field`. - `list` - lists the related values. Must specify the `field`. - `max` - gets the maximum related value. Must specify the `field`. - `min` - gets the minimum related value. Must specify the `field`. - `avg` - gets the average related value. Must specify the `field`. - `custom` - allows for a custom aggregate. Implementation depends on the data layer. Must provide an `implementation`. The declared set of named aggregates can be used by extensions and referred to throughout your application As an escape hatch, they can also be loaded in the query using [`Ash.Query.load/2`](Ash.Query.html#load/2), or after the fact using [`Ash.load/3`](Ash.html#load/3). Aggregates declared on the resource will be keys in the resource's struct. See the docs on `Ash.Resource.Dsl.aggregates` for more information. ## [](aggregates.html#custom-aggregates-in-the-query)Custom aggregates in the query Custom aggregates can be added to the query and will be placed in the `aggregates` key of the results. This is an escape hatch, and is not the primary way that you should be using aggregates. It does, however, allow for dynamism, i.e if you are accepting user input that determines what the filter and/or field should be, that kind of thing. Example: ``` User |> Ash.Query.aggregate( :count_of_posts, :count, :posts, query: [ filter: [published: published?] ] ) ``` See the documentation for [`Ash.Query.aggregate/4`](Ash.Query.html#aggregate/4) for more information. ## [](aggregates.html#join-filters)Join Filters Join filters allows for more complex aggregate queries, including joining with predicates based on multiple related values. ### [](aggregates.html#example)Example ``` aggregates do sum :saved_money, [:redeems, :deal], :amount do # where any redeem of the deal is redeemed filter expr(redeems.redeemed == true) # where the `redeems` are `redeemed` join_filter :redeems, expr(redeemed == true) # where the `redeems.deal.active` == `redeems.require_active` join_filter [:redeems, :deal], expr(active == parent(require_active)) end end ``` ## [](aggregates.html#inline-aggregates)Inline Aggregates Aggregates can be created in-line in expressions, with their relationship path specified and any options provided that match the options given to [`Ash.Query.Aggregate.new/4`](Ash.Query.Aggregate.html#new/4). For example: ``` calculate :grade, :decimal, expr( count(answers, query: [filter: expr(correct == true)]) / count(answers, query: [filter: expr(correct == false)]) ) ``` See the [Expressions guide](expressions.html#inline-aggregates) for more. [← Previous Page Calculations](calculations.html) [Next Page → Validations](validations.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/aggregates.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Alternatives [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/about_ash/alternatives.md#L1 "View Source") There aren't really any alternatives to Ash that we are aware of that do all of the same things, but there are many different packages out there that do some of the things that Ash does. This is a living document, and is not comprehensive. We are not *vouching* for any of these packages, but rather listing them here for your convenience to investigate on your own. Want to add or edit this list? Open a [pull request](https://github.com/ash-project/ash/edit/main/documentation/topics/about_ash/alternatives.md) Want a more comprehensive list? Check out the [Awesome Elixir](https://github.com/h4cc/awesome-elixir). ## [](alternatives.html#application-frameworks)Application Frameworks These frameworks have similar overarching goals of helping you build your application layer. - [Commanded](../commanded.html) - An event sourced application framework. - [Sleeky](../sleeky.html) - Billed as a lightweight alternative to Ash. Inspired by Ash, but more tightly built on top of ecto. ## [](alternatives.html#application-design)Application Design - [Boundary](../boundary.html) - A library for defining boundaries in your application. - [Phoenix Contexts](../phoenix/contexts.html) - Phoenix ships with a concept called "contexts", which provide some generators with application design guidance. ## [](alternatives.html#building-apis)Building APIs - [Absinthe](../absinthe.html) - A GraphQL toolkit for Elixir. This is what `AshGraphql` uses under the hood, but you can also use Absinthe directly. - [Phoenix](../phoenix.html) - Phoenix is a web framework for Elixir. It is not necessarily an API framework, but has all the tools you need to build APIs by hand. - [JSONAPI Elixir](../jsonapi.html) - A library for building JSONAPI compliant APIs in Elixir on top of Ecto. - [Open API Spex](https://github.com/open-api-spex) - A library for generating OpenAPI (Swagger) documentation for your API. We generate these for you in AshJsonApi, but you can use this library to build open api specifications of your hand-written API ## [](alternatives.html#working-with-data)Working with Data - [Ecto](../ecto.html) - Ecto is a database wrapper and query generator for Elixir. In many cases, Ash uses Ecto under the hood, but it is also available to build on top of directly. - [Flop](../flop.html) - A library designed to easily apply filtering, ordering, and pagination to Ecto queries. ## [](alternatives.html#authentication)Authentication - [mix phx.gen.auth](../phoenix/Mix.Tasks.Phx.Gen.Auth.html) - A mix task that generates authentication for a Phoenix application. Some folks prefer to use this over `AshAuthentication` even if they are using Ash. - [Assent](../assent.html) - Multi-provider authentication framework. ## [](alternatives.html#authorization)Authorization - [Bodyguard](../bodyguard.html) - A phoenix-context-based policy authorization framework. ## [](alternatives.html#validation)Validation - [Ecto](../ecto.html) - Ecto can be used to validate data at the edge, using things like schema-less changesets. - [Drops](../drops.html) - a collection of small modules that provide useful extensions and functions that can be used to work with data effectively. - [GuardedStruct](https://github.com/mishka-group/guarded_struct) - validation, sanitization, and construction of structs, supporting nested structs. [← Previous Page Contributing to Ash](contributing-to-ash.html) [Next Page → Changelog](changelog.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/about_ash/alternatives.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # API Reference ash v3.4.58 [View Source](https://github.com/ash-project/ash "View Source") ## [](api-reference.html#modules)Modules [Ash](Ash.html) The primary interface to call actions and interact with resources. [Ash.ActionInput](Ash.ActionInput.html) Input for a custom action [Ash.Actions.Read.AsyncLimiter](Ash.Actions.Read.AsyncLimiter.html) A utility for limiting the number of concurrent async operations [Ash.Authorizer](Ash.Authorizer.html) The interface for an ash authorizer [Ash.BulkResult](Ash.BulkResult.html) The return value for bulk actions. [Ash.Can](Ash.Can.html) Contains the Ash.can function logic. [Ash.Changeset](Ash.Changeset.html) Changesets are used to create and update data in Ash. [Ash.Changeset.ManagedRelationshipHelpers](Ash.Changeset.ManagedRelationshipHelpers.html) Tools for introspecting managed relationships. [Ash.Changeset.OriginalDataNotAvailable](Ash.Changeset.OriginalDataNotAvailable.html) A value placed in changeset.data to indicate that the original data is not available [Ash.CiString](Ash.CiString.html) Represents a case insensitive string [Ash.CodeInterface](Ash.CodeInterface.html) Used to define the functions of a code interface for a resource. [Ash.Context](Ash.Context.html) Functions for working with the context provided to various callbacks in Ash. [Ash.CustomExpression](Ash.CustomExpression.html) A module for defining custom functions that can be called in Ash expressions. [Ash.DataLayer](Ash.DataLayer.html) The behaviour for backing resource actions with persistence layers. [Ash.DataLayer.Ets](Ash.DataLayer.Ets.html) An ETS (Erlang Term Storage) backed Ash Datalayer, for testing and lightweight usage. [Ash.DataLayer.Ets.Info](Ash.DataLayer.Ets.Info.html) Introspection helpers for the Ets data layer [Ash.DataLayer.Mnesia](Ash.DataLayer.Mnesia.html) An Mnesia backed Ash Datalayer. [Ash.DataLayer.Mnesia.Info](Ash.DataLayer.Mnesia.Info.html) Introspection helpers for Ash.DataLayer.Mnesia [Ash.DataLayer.Simple](Ash.DataLayer.Simple.html) A data layer that returns structs. [Ash.DataLayer.Verifiers.RequirePreCheckWith](Ash.DataLayer.Verifiers.RequirePreCheckWith.html) Ensures that all identities have a `pre_check_with` configured, or raises. [Ash.Domain](Ash.Domain.html) A domain allows you to interact with your resources, and holds domain-wide configuration. [Ash.Domain.Dsl.ResourceReference](Ash.Domain.Dsl.ResourceReference.html) A resource reference in a domain [Ash.Domain.Igniter](Ash.Domain.Igniter.html) Codemods for working with Ash.Domain modules [Ash.Domain.Info](Ash.Domain.Info.html) Introspection tools for Ash.Domain [Ash.Domain.Info.Diagram](Ash.Domain.Info.Diagram.html) Generate Mermaid diagrams from a specified domain. [Ash.Domain.Info.Livebook](Ash.Domain.Info.Livebook.html) Generate a Livebook from a specified domain. [Ash.Domain.Verifiers.EnsureNoEmbeds](Ash.Domain.Verifiers.EnsureNoEmbeds.html) Ensures that all resources for a given domain are not embeds. [Ash.Domain.Verifiers.ValidateArgumentsToCodeInterface](Ash.Domain.Verifiers.ValidateArgumentsToCodeInterface.html) Validate the arguments defined in the code interface and reject arguments that are not action attributes/arguments [Ash.Domain.Verifiers.ValidateRelatedResourceInclusion](Ash.Domain.Verifiers.ValidateRelatedResourceInclusion.html) Ensures that all related resources are included in a domain. [Ash.Error](Ash.Error.html) Tools and utilities used by Ash to manage and conform errors [Ash.Error.Action.InvalidArgument](Ash.Error.Action.InvalidArgument.html) Used when an invalid value is provided for an action argument [Ash.Error.Changes.ActionRequiresActor](Ash.Error.Changes.ActionRequiresActor.html) Used when an actor is referenced in a filter template, but no actor exists [Ash.Error.Changes.InvalidArgument](Ash.Error.Changes.InvalidArgument.html) Used when an invalid value is provided for an action argument [Ash.Error.Changes.InvalidAttribute](Ash.Error.Changes.InvalidAttribute.html) Used when an invalid value is provided for an attribute change [Ash.Error.Changes.InvalidChanges](Ash.Error.Changes.InvalidChanges.html) Used when a change is provided that covers multiple attributes/relationships [Ash.Error.Changes.InvalidRelationship](Ash.Error.Changes.InvalidRelationship.html) Used when an invalid value is provided for a relationship change [Ash.Error.Changes.NoSuchAttribute](Ash.Error.Changes.NoSuchAttribute.html) Used when a change is provided for an attribute that does not exist [Ash.Error.Changes.NoSuchRelationship](Ash.Error.Changes.NoSuchRelationship.html) Used when a change is provided for an relationship that does not exist [Ash.Error.Changes.Required](Ash.Error.Changes.Required.html) Used when an attribute or relationship is required [Ash.Error.Changes.StaleRecord](Ash.Error.Changes.StaleRecord.html) Used when a stale record is attempted to be updated or deleted [Ash.Error.Exception](Ash.Error.Exception.html) Tooling for creating an Ash exception [Ash.Error.Forbidden](Ash.Error.Forbidden.html) Used when authorization for an action fails [Ash.Error.Forbidden.CannotFilterCreates](Ash.Error.Forbidden.CannotFilterCreates.html) Used when a create action would be filtered [Ash.Error.Forbidden.DomainRequiresActor](Ash.Error.Forbidden.DomainRequiresActor.html) Used when a domain that has `require_actor? true` is provided no actor [Ash.Error.Forbidden.DomainRequiresAuthorization](Ash.Error.Forbidden.DomainRequiresAuthorization.html) Used when a domain that has `authorize :always` is provided authorize?: false [Ash.Error.Forbidden.ForbiddenField](Ash.Error.Forbidden.ForbiddenField.html) Raised in cases where access to a specific field was prevented [Ash.Error.Forbidden.InitialDataRequired](Ash.Error.Forbidden.InitialDataRequired.html) Used when initial data was not supplied when it was required [Ash.Error.Forbidden.MustPassStrictCheck](Ash.Error.Forbidden.MustPassStrictCheck.html) Used when unreachable code/conditions are reached in the framework [Ash.Error.Forbidden.Placeholder](Ash.Error.Forbidden.Placeholder.html) A placeholder exception that the user should never see [Ash.Error.Forbidden.Policy](Ash.Error.Forbidden.Policy.html) Raised when policy authorization for an action fails [Ash.Error.Framework](Ash.Error.Framework.html) Used when an unknown/generic framework error occurs [Ash.Error.Framework.AssumptionFailed](Ash.Error.Framework.AssumptionFailed.html) Used when unreachable code/conditions are reached in the framework [Ash.Error.Framework.CanNotBeAtomic](Ash.Error.Framework.CanNotBeAtomic.html) Used when a change that is only atomic cannot be done atomically [Ash.Error.Framework.FlagAssertionFailed](Ash.Error.Framework.FlagAssertionFailed.html) Used when unreachable code/conditions are reached in the framework [Ash.Error.Framework.InvalidReturnType](Ash.Error.Framework.InvalidReturnType.html) Used when a callback returns an invalid type [Ash.Error.Framework.MustBeAtomic](Ash.Error.Framework.MustBeAtomic.html) Used when an action that must be atomic cannot be done atomically [Ash.Error.Framework.SynchronousEngineStuck](Ash.Error.Framework.SynchronousEngineStuck.html) Used when the sycnrhonous engine cannot proceed [Ash.Error.Invalid](Ash.Error.Invalid.html) The top level invalid error [Ash.Error.Invalid.ActionRequiresPagination](Ash.Error.Invalid.ActionRequiresPagination.html) Used when page option is passed but pagination is not enabled. [Ash.Error.Invalid.AtomicsNotSupported](Ash.Error.Invalid.AtomicsNotSupported.html) Used when atomics for the given action type are not not supported by the data layer, but one is used. [Ash.Error.Invalid.InvalidPrimaryKey](Ash.Error.Invalid.InvalidPrimaryKey.html) Used when an invalid primary key is given to [`Ash.get/2`](Ash.html#get/2) [Ash.Error.Invalid.LimitRequired](Ash.Error.Invalid.LimitRequired.html) Used when no limit is provided, pagination is required, and no default page size is configured [Ash.Error.Invalid.MultipleResults](Ash.Error.Invalid.MultipleResults.html) Used when multiple results are returned in a case where only one result was expected [Ash.Error.Invalid.NoIdentityFound](Ash.Error.Invalid.NoIdentityFound.html) Used when an identity name is used that does not reference identity on the resource [Ash.Error.Invalid.NoMatchingBulkStrategy](Ash.Error.Invalid.NoMatchingBulkStrategy.html) Used when an identity name is used that does not reference identity on the resource [Ash.Error.Invalid.NoPrimaryAction](Ash.Error.Invalid.NoPrimaryAction.html) Used when an action name is provided that doesn't exist [Ash.Error.Invalid.NoSuchAction](Ash.Error.Invalid.NoSuchAction.html) Used when an action name is provided that doesn't exist [Ash.Error.Invalid.NoSuchInput](Ash.Error.Invalid.NoSuchInput.html) Used when an input is provided to an action or calculation that is not accepted [Ash.Error.Invalid.NoSuchResource](Ash.Error.Invalid.NoSuchResource.html) Used when a resource or alias is provided that doesn't exist [Ash.Error.Invalid.NonCountableAction](Ash.Error.Invalid.NonCountableAction.html) Used when page\[:count] option is passed but the action's pagination is not countable. [Ash.Error.Invalid.NonStreamableAction](Ash.Error.Invalid.NonStreamableAction.html) Used when Ash.stream is used with an action that does not support keyset pagination [Ash.Error.Invalid.PaginationRequired](Ash.Error.Invalid.PaginationRequired.html) Used when `page: false` is provided but pagination is required [Ash.Error.Invalid.ResourceNotAllowed](Ash.Error.Invalid.ResourceNotAllowed.html) Used when a resource or alias is provided that cannot be used with the given domain [Ash.Error.Invalid.TenantRequired](Ash.Error.Invalid.TenantRequired.html) Used when a tenant is not specified [Ash.Error.Invalid.Timeout](Ash.Error.Invalid.Timeout.html) Used when a request to a domain times out. [Ash.Error.Invalid.TimeoutNotSupported](Ash.Error.Invalid.TimeoutNotSupported.html) Used when timeouts are not supported by the data layer, but one is set [Ash.Error.Invalid.Unavailable](Ash.Error.Invalid.Unavailable.html) Used when a given resource is unavailable. [Ash.Error.Load.InvalidQuery](Ash.Error.Load.InvalidQuery.html) Used when an invalid query is provided in a load [Ash.Error.Load.NoSuchRelationship](Ash.Error.Load.NoSuchRelationship.html) Used when attempting to load a relationship that does not exist [Ash.Error.Page.InvalidKeyset](Ash.Error.Page.InvalidKeyset.html) Used when a value is provided for a keyset that cannot be Base64 decoded. [Ash.Error.Query.AggregatesNotSupported](Ash.Error.Query.AggregatesNotSupported.html) Used when the data\_layer does not support aggregates, or filtering/sorting them [Ash.Error.Query.CalculationRequiresPrimaryKey](Ash.Error.Query.CalculationRequiresPrimaryKey.html) Used when a calculation requires a primary key but was not supplied with one [Ash.Error.Query.CalculationsNotSupported](Ash.Error.Query.CalculationsNotSupported.html) Used when the data\_layer does not support calculations, or filtering/sorting them [Ash.Error.Query.InvalidArgument](Ash.Error.Query.InvalidArgument.html) Used when an invalid value is provided for an action argument [Ash.Error.Query.InvalidCalculationArgument](Ash.Error.Query.InvalidCalculationArgument.html) Used when an invalid value is provided for a calculation argument [Ash.Error.Query.InvalidExpression](Ash.Error.Query.InvalidExpression.html) Used when an invalid expression is used in a filter [Ash.Error.Query.InvalidFilterReference](Ash.Error.Query.InvalidFilterReference.html) Used when an invalid reference is used in a filter [Ash.Error.Query.InvalidFilterValue](Ash.Error.Query.InvalidFilterValue.html) Used when an invalid value is provided for a filter [Ash.Error.Query.InvalidLimit](Ash.Error.Query.InvalidLimit.html) Used when an invalid limit is provided [Ash.Error.Query.InvalidLoad](Ash.Error.Query.InvalidLoad.html) Used when an invalid load is provided [Ash.Error.Query.InvalidOffset](Ash.Error.Query.InvalidOffset.html) Used when an invalid offset is provided [Ash.Error.Query.InvalidPage](Ash.Error.Query.InvalidPage.html) Used when an invalid page option is provided [Ash.Error.Query.InvalidQuery](Ash.Error.Query.InvalidQuery.html) A generic error that can be used to add an error to a query for a specific field [Ash.Error.Query.InvalidSortOrder](Ash.Error.Query.InvalidSortOrder.html) Used when an invalid sort order is provided [Ash.Error.Query.LockNotSupported](Ash.Error.Query.LockNotSupported.html) Used when the data\_layer does not support a given lock type [Ash.Error.Query.NoComplexSortsWithKeysetPagination](Ash.Error.Query.NoComplexSortsWithKeysetPagination.html) Due to the filter-based implementation of keyset pagination, it cannot be used with sorts on calculations. [Ash.Error.Query.NoReadAction](Ash.Error.Query.NoReadAction.html) Used when a resource would be read but has no read action [Ash.Error.Query.NoSuchAttribute](Ash.Error.Query.NoSuchAttribute.html) Used when an attribute that doesn't exist is used in a query [Ash.Error.Query.NoSuchField](Ash.Error.Query.NoSuchField.html) Used when a field(attrbute, calculation, aggregate or relationship) that doesn't exist is used in a query [Ash.Error.Query.NoSuchFilterPredicate](Ash.Error.Query.NoSuchFilterPredicate.html) Used when a filter predicate that does not exist is referenced [Ash.Error.Query.NoSuchFunction](Ash.Error.Query.NoSuchFunction.html) Used when an function that doesn't exist is used in a query [Ash.Error.Query.NoSuchOperator](Ash.Error.Query.NoSuchOperator.html) Used when an operator that doesn't exist is used in a query [Ash.Error.Query.NoSuchRelationship](Ash.Error.Query.NoSuchRelationship.html) Used when an relationship that doesn't exist is used in a query [Ash.Error.Query.NotFound](Ash.Error.Query.NotFound.html) Used when an entity that not exist is referenced [Ash.Error.Query.ReadActionRequired](Ash.Error.Query.ReadActionRequired.html) Used when a relationship is filtered and the destination does not have a default read action [Ash.Error.Query.ReadActionRequiresActor](Ash.Error.Query.ReadActionRequiresActor.html) Used when an actor is referenced in a filter template, but no actor exists [Ash.Error.Query.Required](Ash.Error.Query.Required.html) Used when a filter or argument is required in a query [Ash.Error.Query.UnsortableField](Ash.Error.Query.UnsortableField.html) Used when attempting to sort on a field that cannot be used for sorting [Ash.Error.Query.UnsupportedPredicate](Ash.Error.Query.UnsupportedPredicate.html) Used when the data\_layer does not support a provided predicate [Ash.Error.SimpleDataLayer.NoDataProvided](Ash.Error.SimpleDataLayer.NoDataProvided.html) Used when no data was provided to the simple data layer [Ash.Error.Stacktrace](Ash.Error.Stacktrace.html) A placeholder for a stacktrace so that we can avoid printing it everywhere [Ash.Error.Unknown](Ash.Error.Unknown.html) The top level unknown error container [Ash.Error.Unknown.UnknownError](Ash.Error.Unknown.UnknownError.html) Used when an unknown error occurs [Ash.Expr](Ash.Expr.html) Tools to build Ash expressions [Ash.Extension](Ash.Extension.html) A behavior of additional callbacks that extensions can implement, specific to Ash. [Ash.Filter](Ash.Filter.html) The representation of a filter in Ash. [Ash.Filter.Predicate](Ash.Filter.Predicate.html) Represents a predicate which can be simplified and/or compared with other predicates [Ash.Filter.Runtime](Ash.Filter.Runtime.html) Checks a record to see if it matches a filter statement. [Ash.Filter.Simple](Ash.Filter.Simple.html) Represents a simplified filter, with a simple list of predicates [Ash.Filter.Simple.Not](Ash.Filter.Simple.Not.html) A negated predicate [Ash.ForbiddenField](Ash.ForbiddenField.html) Represents a field that was hidden due to authorization rules. [Ash.Generator](Ash.Generator.html) Tools for generating input to Ash resource actions and for generating seed data. [Ash.Igniter](Ash.Igniter.html) Codemods and utilities for working with Ash &amp; Igniter [Ash.Mix.Tasks.Helpers](Ash.Mix.Tasks.Helpers.html) Helpers for Ash Mix tasks. [Ash.NotLoaded](Ash.NotLoaded.html) Used when a field hasn't been loaded or selected. [Ash.Notifier](Ash.Notifier.html) A notifier is an extension that receives various events [Ash.Notifier.Notification](Ash.Notifier.Notification.html) Represents a notification that will be handled by a resource's notifiers [Ash.Notifier.PubSub](Ash.Notifier.PubSub.html) A builtin notifier to help you publish events over any kind of pub-sub tooling. [Ash.Notifier.PubSub.Info](Ash.Notifier.PubSub.Info.html) Introspection helpers for Ash.Notifier.PubSub [Ash.Notifier.PubSub.Publication](Ash.Notifier.PubSub.Publication.html) Represents a configured publication from the pubsub notifier on an Ash.Resource [Ash.OptionsHelpers](Ash.OptionsHelpers.html) Helpers for working with nimble options [Ash.Page](Ash.Page.html) Types for Ash pages [Ash.Page.Keyset](Ash.Page.Keyset.html) A page of results from `keyset` based pagination. [Ash.Page.Offset](Ash.Page.Offset.html) A page of results from `offset` based pagination. [Ash.PlugHelpers](Ash.PlugHelpers.html) Helpers for working with the Plug connection. [Ash.Policy.Authorizer](Ash.Policy.Authorizer.html) An authorization extension for ash resources. [Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html) Adds field policies for any missing fields [Ash.Policy.Authorizer.Transformers.CacheFieldPolicies](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html) Cache field policies for each field [Ash.Policy.Chart.Mermaid](Ash.Policy.Chart.Mermaid.html) Generates policy mermaid charts [Ash.Policy.Check](Ash.Policy.Check.html) A behaviour for declaring checks, which can be used to easily construct authorization rules. [Ash.Policy.Check.AccessingFrom](Ash.Policy.Check.AccessingFrom.html) This check is true when the current action is being run "through" a relationship. [Ash.Policy.Check.Action](Ash.Policy.Check.Action.html) This check is true when the action name matches the provided action name. [Ash.Policy.Check.ActionType](Ash.Policy.Check.ActionType.html) This check is true when the action type matches the provided type [Ash.Policy.Check.ActorAbsent](Ash.Policy.Check.ActorAbsent.html) This check is true when the actor is `nil`, and false when the actor is specified. [Ash.Policy.Check.ActorAttributeEquals](Ash.Policy.Check.ActorAttributeEquals.html) This check is true when the value of the specified attribute of the actor equals the specified value. [Ash.Policy.Check.ActorPresent](Ash.Policy.Check.ActorPresent.html) This check is true when there is an actor specified, and false when the actor is `nil`. [Ash.Policy.Check.Builtins](Ash.Policy.Check.Builtins.html) The global authorization checks built into ash [Ash.Policy.Check.ChangingAttributes](Ash.Policy.Check.ChangingAttributes.html) This check is true when attribute changes correspond to the provided options. [Ash.Policy.Check.ChangingRelationships](Ash.Policy.Check.ChangingRelationships.html) This check is true when the specified relationship is changing [Ash.Policy.Check.ContextEquals](Ash.Policy.Check.ContextEquals.html) This check is true when the value of the specified key or path in the changeset or query context equals the specified value. [Ash.Policy.Check.Expression](Ash.Policy.Check.Expression.html) The check module used for `expr`s in policies [Ash.Policy.Check.FilteringOn](Ash.Policy.Check.FilteringOn.html) This check is true when the field provided is being referenced anywhere in a filter statement. [Ash.Policy.Check.Loading](Ash.Policy.Check.Loading.html) This check is true when the field or relationship, or path to field, is being loaded and false when it is not. [Ash.Policy.Check.Matches](Ash.Policy.Check.Matches.html) This check is true when the specified function returns true [Ash.Policy.Check.RelatesToActorVia](Ash.Policy.Check.RelatesToActorVia.html) This check passes if the data relates to the actor via the specified relationship or path of relationships. [Ash.Policy.Check.RelatingToActor](Ash.Policy.Check.RelatingToActor.html) This check is true when the specified relationship is being changed to the current actor. [Ash.Policy.Check.Resource](Ash.Policy.Check.Resource.html) This check is true when the resource matches the provided resource name or names. [Ash.Policy.Check.Selecting](Ash.Policy.Check.Selecting.html) This check is true when the field is being selected and false when it is not. [Ash.Policy.Check.Static](Ash.Policy.Check.Static.html) This check is always the result provided [Ash.Policy.FieldPolicy](Ash.Policy.FieldPolicy.html) Represents a field policy in an Ash.Resource [Ash.Policy.FilterCheck](Ash.Policy.FilterCheck.html) A type of check that is represented by a filter statement [Ash.Policy.Info](Ash.Policy.Info.html) An authorization extension for ash resources. [Ash.Policy.Policy](Ash.Policy.Policy.html) Represents a policy on an Ash.Resource [Ash.Policy.PolicyGroup](Ash.Policy.PolicyGroup.html) Represents a policy group on an Ash.Resource [Ash.Policy.SimpleCheck](Ash.Policy.SimpleCheck.html) A type of check that operates only on request context, never on the data [Ash.ProcessHelpers](Ash.ProcessHelpers.html) Helpers for working with processes and Ash actions. [Ash.Query](Ash.Query.html) A data structure for reading data from a resource. [Ash.Query.Aggregate](Ash.Query.Aggregate.html) Represents an aggregated association value [Ash.Query.BooleanExpression](Ash.Query.BooleanExpression.html) Represents a boolean expression [Ash.Query.Calculation](Ash.Query.Calculation.html) Represents a calculated attribute requested on a query [Ash.Query.Call](Ash.Query.Call.html) Represents a function call/AST node in an Ash query expression [Ash.Query.Exists](Ash.Query.Exists.html) Determines if a given related entity exists. [Ash.Query.Function](Ash.Query.Function.html) A function is a predicate with an arguments list. [Ash.Query.Function.Ago](Ash.Query.Function.Ago.html) Subtracts the given interval from the current time in UTC. [Ash.Query.Function.At](Ash.Query.Function.At.html) Gets an element in the list by index [Ash.Query.Function.CompositeType](Ash.Query.Function.CompositeType.html) Constructs a composite type in a way that is natively understood by the data layer [Ash.Query.Function.Contains](Ash.Query.Function.Contains.html) Returns true if the first string contains the second. [Ash.Query.Function.CountNils](Ash.Query.Function.CountNils.html) Returns the count of nil. [Ash.Query.Function.DateAdd](Ash.Query.Function.DateAdd.html) Adds the given interval to the current time in UTC [Ash.Query.Function.DateTimeAdd](Ash.Query.Function.DateTimeAdd.html) Adds the given interval to the current time in UTC [Ash.Query.Function.Error](Ash.Query.Function.Error.html) If the predicate is truthy, the provided exception is raised with the provided values. [Ash.Query.Function.Fragment](Ash.Query.Function.Fragment.html) Adds the given interval from the current time in UTC. [Ash.Query.Function.FromNow](Ash.Query.Function.FromNow.html) Adds the given interval from the current time in UTC. [Ash.Query.Function.GetPath](Ash.Query.Function.GetPath.html) Gets the value at the provided path in the value, which must be a map or embed. [Ash.Query.Function.If](Ash.Query.Function.If.html) If predicate is truthy, then the second argument is returned, otherwise the third. [Ash.Query.Function.IsNil](Ash.Query.Function.IsNil.html) true if the provided field is nil [Ash.Query.Function.Lazy](Ash.Query.Function.Lazy.html) Runs the provided MFA and returns the result as a known value. [Ash.Query.Function.Length](Ash.Query.Function.Length.html) Returns the length of a list attribute defined by the composite type `{:array, Type}`. [Ash.Query.Function.Minus](Ash.Query.Function.Minus.html) Multiplies the value by negative one [Ash.Query.Function.Now](Ash.Query.Function.Now.html) Returns the current datetime [Ash.Query.Function.Round](Ash.Query.Function.Round.html) Rounds a float, decimal or integer to the given number of points [Ash.Query.Function.StartOfDay](Ash.Query.Function.StartOfDay.html) Converts a date or datetime into the start of day [Ash.Query.Function.StringDowncase](Ash.Query.Function.StringDowncase.html) Downcase a string [Ash.Query.Function.StringJoin](Ash.Query.Function.StringJoin.html) Joins a list of values. [Ash.Query.Function.StringLength](Ash.Query.Function.StringLength.html) Trims whitespace from a string [Ash.Query.Function.StringSplit](Ash.Query.Function.StringSplit.html) Split a string into a list of strings [Ash.Query.Function.StringTrim](Ash.Query.Function.StringTrim.html) Trims whitespace from a string [Ash.Query.Function.Today](Ash.Query.Function.Today.html) Returns the current date. [Ash.Query.Function.Type](Ash.Query.Function.Type.html) Casts the value to a given type. Can also be used to provide type hints to data layers, where appropriate. [Ash.Query.Not](Ash.Query.Not.html) Represents the negation of the contained expression [Ash.Query.Operator](Ash.Query.Operator.html) An operator is a predicate with a `left` and a `right` [Ash.Query.Operator.Eq](Ash.Query.Operator.Eq.html) left == right [Ash.Query.Operator.GreaterThan](Ash.Query.Operator.GreaterThan.html) left &gt; right [Ash.Query.Operator.GreaterThanOrEqual](Ash.Query.Operator.GreaterThanOrEqual.html) left &gt;= right [Ash.Query.Operator.In](Ash.Query.Operator.In.html) left in \[1, 2, 3] [Ash.Query.Operator.IsNil](Ash.Query.Operator.IsNil.html) left is\_nil true/false [Ash.Query.Operator.LessThan](Ash.Query.Operator.LessThan.html) left &lt; right [Ash.Query.Operator.LessThanOrEqual](Ash.Query.Operator.LessThanOrEqual.html) left &lt;= right [Ash.Query.Operator.NotEq](Ash.Query.Operator.NotEq.html) left != right [Ash.Query.Parent](Ash.Query.Parent.html) Used to access values from the "source" of a given expression. [Ash.Query.Ref](Ash.Query.Ref.html) Represents a relation/attribute reference [Ash.Query.UpsertConflict](Ash.Query.UpsertConflict.html) Returns the conflicting new information. [Ash.Reactor](Ash.Reactor.html) [`Ash.Reactor`](Ash.Reactor.html) is a [`Reactor`](https://hex.pm/packages/reactor) extension which provides steps for working with Ash resources and actions. [Ash.Reactor.ActionStep](Ash.Reactor.ActionStep.html) The Reactor step which is used to execute generic actions. [Ash.Reactor.AshStep](Ash.Reactor.AshStep.html) A reactor step which runs a step-module or an anonymous function, and enqueues any returned notifications before returning. [Ash.Reactor.BulkCreateStep](Ash.Reactor.BulkCreateStep.html) The Reactor stop which is used to execute create actions in bulk. [Ash.Reactor.BulkUpdateStep](Ash.Reactor.BulkUpdateStep.html) The Reactor stop which is used to execute create actions in bulk. [Ash.Reactor.ChangeStep](Ash.Reactor.ChangeStep.html) The Reactor step which is used to execute change steps. [Ash.Reactor.CreateStep](Ash.Reactor.CreateStep.html) The Reactor step which is used to execute create actions. [Ash.Reactor.DestroyStep](Ash.Reactor.DestroyStep.html) The Reactor step which is used to execute update actions. [Ash.Reactor.Dsl.Action](Ash.Reactor.Dsl.Action.html) The `action` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.ActionLoad](Ash.Reactor.Dsl.ActionLoad.html) Add a load statement to an action. [Ash.Reactor.Dsl.ActionTransformer](Ash.Reactor.Dsl.ActionTransformer.html) Responsible for transforming actions. [Ash.Reactor.Dsl.Actor](Ash.Reactor.Dsl.Actor.html) Specify the actor used to execute an action. [Ash.Reactor.Dsl.AshStep](Ash.Reactor.Dsl.AshStep.html) The ash\_step DSL module. [Ash.Reactor.Dsl.BulkCreate](Ash.Reactor.Dsl.BulkCreate.html) The `bulk_create` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.BulkUpdate](Ash.Reactor.Dsl.BulkUpdate.html) The `bulk_update` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.Change](Ash.Reactor.Dsl.Change.html) The `change` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.Context](Ash.Reactor.Dsl.Context.html) Specify context to merge into an action's context. [Ash.Reactor.Dsl.Create](Ash.Reactor.Dsl.Create.html) The `create` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.Destroy](Ash.Reactor.Dsl.Destroy.html) The `destroy` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.Inputs](Ash.Reactor.Dsl.Inputs.html) The `inputs` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.Load](Ash.Reactor.Dsl.Load.html) The `load` step entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.MiddlewareTransformer](Ash.Reactor.Dsl.MiddlewareTransformer.html) Ensures that the required middlewares are added to the Reactor. [Ash.Reactor.Dsl.Read](Ash.Reactor.Dsl.Read.html) The `read` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.ReadOne](Ash.Reactor.Dsl.ReadOne.html) The `read_one` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.Tenant](Ash.Reactor.Dsl.Tenant.html) Specify the tenant used to execute an action. [Ash.Reactor.Dsl.Transaction](Ash.Reactor.Dsl.Transaction.html) The `transaction` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.Dsl.Update](Ash.Reactor.Dsl.Update.html) The `update` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. [Ash.Reactor.LoadStep](Ash.Reactor.LoadStep.html) The Reactor step which is used to execute load steps. [Ash.Reactor.MergeInputsStep](Ash.Reactor.MergeInputsStep.html) A custom step which merges any number of `inputs` results into a single map. [Ash.Reactor.Notifications](Ash.Reactor.Notifications.html) Reactor middleware used to collect and emit notifications upon successful completion of the Reactor. [Ash.Reactor.ReadOneStep](Ash.Reactor.ReadOneStep.html) The Reactor step which is used to execute get actions. [Ash.Reactor.ReadStep](Ash.Reactor.ReadStep.html) The Reactor step which is used to execute read actions. [Ash.Reactor.Tracer](Ash.Reactor.Tracer.html) Reactor middleware which threads Ash's tracing information through to new processes spawned by Reactor. [Ash.Reactor.TransactionStep](Ash.Reactor.TransactionStep.html) The Reactor step which is used to wrap other steps in an Ash data layer transaction. [Ash.Reactor.UpdateStep](Ash.Reactor.UpdateStep.html) The Reactor step which is used to execute update actions. [Ash.Resource](Ash.Resource.html) A resource is a static definition of an entity in your system. [Ash.Resource.Actions](Ash.Resource.Actions.html) Types for Ash actions [Ash.Resource.Actions.Action](Ash.Resource.Actions.Action.html) Represents a custom action on a resource. [Ash.Resource.Actions.Argument](Ash.Resource.Actions.Argument.html) Represents an argument to an action [Ash.Resource.Actions.Create](Ash.Resource.Actions.Create.html) Represents a create action on a resource. [Ash.Resource.Actions.Destroy](Ash.Resource.Actions.Destroy.html) Represents a destroy action on a resource. [Ash.Resource.Actions.Implementation](Ash.Resource.Actions.Implementation.html) An implementation of a generic action. [Ash.Resource.Actions.Implementation.Context](Ash.Resource.Actions.Implementation.Context.html) The context passed into generic action functions [Ash.Resource.Actions.Metadata](Ash.Resource.Actions.Metadata.html) Represents metadata from an action [Ash.Resource.Actions.Read](Ash.Resource.Actions.Read.html) Represents a read action on a resource. [Ash.Resource.Actions.Read.Pagination](Ash.Resource.Actions.Read.Pagination.html) Represents the pagination configuration of a read action [Ash.Resource.Actions.Update](Ash.Resource.Actions.Update.html) Represents a update action on a resource. [Ash.Resource.Aggregate](Ash.Resource.Aggregate.html) Represents a named aggregate on the resource that can be loaded [Ash.Resource.Aggregate.CustomAggregate](Ash.Resource.Aggregate.CustomAggregate.html) The root behavior for a custom aggregate. [Ash.Resource.Aggregate.JoinFilter](Ash.Resource.Aggregate.JoinFilter.html) Represents a join filter on a resource aggregate [Ash.Resource.Attribute](Ash.Resource.Attribute.html) Represents an attribute on a resource [Ash.Resource.Attribute.Helpers](Ash.Resource.Attribute.Helpers.html) Helpers for building attributes [Ash.Resource.Builder](Ash.Resource.Builder.html) Tools for transforming resources in DSL Transformers. [Ash.Resource.Calculation](Ash.Resource.Calculation.html) The behaviour for defining a module calculation, and the struct for storing a defined calculation. [Ash.Resource.Calculation.Argument](Ash.Resource.Calculation.Argument.html) An argument to a calculation [Ash.Resource.Calculation.Builtins](Ash.Resource.Calculation.Builtins.html) Built in calculations that are automatically imported in the calculations section [Ash.Resource.Calculation.Context](Ash.Resource.Calculation.Context.html) The context and arguments of a calculation [Ash.Resource.Calculation.LoadAttribute](Ash.Resource.Calculation.LoadAttribute.html) Loads an attribute as a calculation. [Ash.Resource.Calculation.LoadRelationship](Ash.Resource.Calculation.LoadRelationship.html) Loads a relationship as a calculation. [Ash.Resource.CalculationInterface](Ash.Resource.CalculationInterface.html) Represents a function that evaluates a calculation in a resource's code interface [Ash.Resource.Change](Ash.Resource.Change.html) The behaviour for an action-specific resource change. [Ash.Resource.Change.Builtins](Ash.Resource.Change.Builtins.html) Built in changes that are available to all resources [Ash.Resource.Change.CascadeDestroy](Ash.Resource.Change.CascadeDestroy.html) Cascade a resource's destroy action to a related resource's destroy action. [Ash.Resource.Change.CascadeUpdate](Ash.Resource.Change.CascadeUpdate.html) Cascade a resource's update action to a related resource's update action. [Ash.Resource.Change.Context](Ash.Resource.Change.Context.html) The context for a change. [Ash.Resource.Change.GetAndLock](Ash.Resource.Change.GetAndLock.html) Refetches the record being updated or destroyed, and locks it with the given type. [Ash.Resource.Change.GetAndLockForUpdate](Ash.Resource.Change.GetAndLockForUpdate.html) Refetches the record being updated or destroyed, and locks it for update. [Ash.Resource.Change.Increment](Ash.Resource.Change.Increment.html) Increments an attribute's value by the amount specified, which defaults to 1. [Ash.Resource.Change.OptimisticLock](Ash.Resource.Change.OptimisticLock.html) Apply an "optimistic lock" on a record being updated or destroyed. [Ash.Resource.Dsl.Filter](Ash.Resource.Dsl.Filter.html) Introspection target for a filter for read actions and relationships [Ash.Resource.Identity](Ash.Resource.Identity.html) Represents a unique constraint on a resource [Ash.Resource.Igniter](Ash.Resource.Igniter.html) Codemods for working with Ash.Resource modules [Ash.Resource.Info](Ash.Resource.Info.html) Introspection for resources [Ash.Resource.Interface](Ash.Resource.Interface.html) Represents a function in a resource's code interface [Ash.Resource.ManualCreate](Ash.Resource.ManualCreate.html) A module to implement manual create actions. [Ash.Resource.ManualCreate.Context](Ash.Resource.ManualCreate.Context.html) The context passed into manual update action functions [Ash.Resource.ManualDestroy](Ash.Resource.ManualDestroy.html) A module to implement manual destroy actions. [Ash.Resource.ManualDestroy.Context](Ash.Resource.ManualDestroy.Context.html) The context passed into manual update action functions [Ash.Resource.ManualRead](Ash.Resource.ManualRead.html) A module to implement manual read actions. [Ash.Resource.ManualRelationship](Ash.Resource.ManualRelationship.html) A module to implement manual relationships. [Ash.Resource.ManualRelationship.Context](Ash.Resource.ManualRelationship.Context.html) The context passed into manual relationship functions [Ash.Resource.ManualUpdate](Ash.Resource.ManualUpdate.html) A module to implement manual update actions. [Ash.Resource.ManualUpdate.Context](Ash.Resource.ManualUpdate.Context.html) The context passed into manual update action functions [Ash.Resource.Preparation](Ash.Resource.Preparation.html) The behaviour for an action-specific query preparation. [Ash.Resource.Preparation.Builtins](Ash.Resource.Preparation.Builtins.html) Builtin query preparations [Ash.Resource.Preparation.Context](Ash.Resource.Preparation.Context.html) The context for a preparation. [Ash.Resource.Relationships](Ash.Resource.Relationships.html) Types Ash relationships [Ash.Resource.Relationships.BelongsTo](Ash.Resource.Relationships.BelongsTo.html) Represents a belongs\_to relationship on a resource [Ash.Resource.Relationships.HasMany](Ash.Resource.Relationships.HasMany.html) Represents a has\_many relationship on a resource [Ash.Resource.Relationships.HasOne](Ash.Resource.Relationships.HasOne.html) Represents a has\_one relationship on a resource [Ash.Resource.Relationships.ManyToMany](Ash.Resource.Relationships.ManyToMany.html) Represents a many\_to\_many relationship on a resource [Ash.Resource.Transformers.AttributesByName](Ash.Resource.Transformers.AttributesByName.html) Persists attribute\_names and attributes\_by\_name. [Ash.Resource.Transformers.BelongsToAttribute](Ash.Resource.Transformers.BelongsToAttribute.html) Creates the attribute for belongs\_to relationships that have `define_attribute?: true` [Ash.Resource.Transformers.CacheActionInputs](Ash.Resource.Transformers.CacheActionInputs.html) Stores the set of valid input keys for each action [Ash.Resource.Transformers.CacheCalculations](Ash.Resource.Transformers.CacheCalculations.html) Persists commonly used calculation information. [Ash.Resource.Transformers.CachePrimaryKey](Ash.Resource.Transformers.CachePrimaryKey.html) Validates and caches the primary key of a resource [Ash.Resource.Transformers.CacheRelationships](Ash.Resource.Transformers.CacheRelationships.html) Persists commonly used relationship information. [Ash.Resource.Transformers.CacheUniqueKeys](Ash.Resource.Transformers.CacheUniqueKeys.html) Stores the set of unique keys for a resource [Ash.Resource.Transformers.CreateJoinRelationship](Ash.Resource.Transformers.CreateJoinRelationship.html) Creates an automatically named `has_many` relationship for each many\_to\_many. [Ash.Resource.Transformers.DefaultAccept](Ash.Resource.Transformers.DefaultAccept.html) Sets the default `accept` for each action [Ash.Resource.Transformers.GetByReadActions](Ash.Resource.Transformers.GetByReadActions.html) Transform any read actions which contain a `get_by` option. [Ash.Resource.Transformers.HasDestinationField](Ash.Resource.Transformers.HasDestinationField.html) Guesses the `destination_attribute` for has many and has one relationships unless provided [Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html) Guesses the `destination_attribute_on_join_resource` for many to many relationships unless provided. [Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html) Guesses the `source_attribute_on_join_resource` for many to many relationships unless provided. [Ash.Resource.Transformers.RequireUniqueActionNames](Ash.Resource.Transformers.RequireUniqueActionNames.html) Ensures that all actions have unique names. [Ash.Resource.Transformers.RequireUniqueFieldNames](Ash.Resource.Transformers.RequireUniqueFieldNames.html) Confirms that a resource does not have multiple fields(attributes, calculations, aggregates, and relationships) with the same name. [Ash.Resource.Transformers.SetPrimaryActions](Ash.Resource.Transformers.SetPrimaryActions.html) Validates the primary action configuration [Ash.Resource.Transformers.SetRelationshipSource](Ash.Resource.Transformers.SetRelationshipSource.html) Sets the `source` key on relationships to be the resource they were defined on [Ash.Resource.Transformers.ValidationsAndChangesForType](Ash.Resource.Transformers.ValidationsAndChangesForType.html) Persists global changes/validations and what type they go on. [Ash.Resource.Validation](Ash.Resource.Validation.html) Represents a validation in Ash. [Ash.Resource.Validation.ActionIs](Ash.Resource.Validation.ActionIs.html) Validates that the action is the specified action. [Ash.Resource.Validation.Builtins](Ash.Resource.Validation.Builtins.html) Built in validations that are available to all resources [Ash.Resource.Validation.Context](Ash.Resource.Validation.Context.html) Context for a validation. [Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation](Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation.html) Ensures that the field at the end of the path is an attribute or calculation. [Ash.Resource.Verifiers.NoReservedFieldNames](Ash.Resource.Verifiers.NoReservedFieldNames.html) Confirms that a resource does not use reserved names for field names. [Ash.Resource.Verifiers.ValidateAccept](Ash.Resource.Verifiers.ValidateAccept.html) Validates that accept and reject lists only contain valid attributes [Ash.Resource.Verifiers.ValidateActionTypesSupported](Ash.Resource.Verifiers.ValidateActionTypesSupported.html) Confirms that all action types declared on a resource are supported by its data layer [Ash.Resource.Verifiers.ValidateAggregatesSupported](Ash.Resource.Verifiers.ValidateAggregatesSupported.html) Confirms that all aggregates are supported by the data layer [Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface](Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface.html) Validate the arguments defined in the code interface and reject arguments that are not action attributes/arguments [Ash.Resource.Verifiers.ValidateEagerIdentities](Ash.Resource.Verifiers.ValidateEagerIdentities.html) Confirms that eager identities are not declared on a resource with no primary read. [Ash.Resource.Verifiers.ValidateManagedRelationshipOpts](Ash.Resource.Verifiers.ValidateManagedRelationshipOpts.html) Confirms that all action types declared on a resource are supported by its data layer [Ash.Resource.Verifiers.ValidateMultitenancy](Ash.Resource.Verifiers.ValidateMultitenancy.html) Ensures that the multitenancy configuration is valid for the given resource [Ash.Resource.Verifiers.ValidatePrimaryKey](Ash.Resource.Verifiers.ValidatePrimaryKey.html) Validates and caches the primary key of a resource [Ash.Resource.Verifiers.ValidateRelationshipAttributes](Ash.Resource.Verifiers.ValidateRelationshipAttributes.html) Validates that all relationships point to valid fields [Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch](Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch.html) Shows a warning on potentially incompatible relationship attributes. [Ash.Resource.Verifiers.VerifyActionsAtomic](Ash.Resource.Verifiers.VerifyActionsAtomic.html) Raises an error on update or destroy actions with `require_atomic?` set to true when it is known at compile time that they will not be atomic. [Ash.Resource.Verifiers.VerifyGenericActionReactorInputs](Ash.Resource.Verifiers.VerifyGenericActionReactorInputs.html) Returns an error if a generic action calls a Reactor module without specifying an argument for all expected inputs. [Ash.Resource.Verifiers.VerifyIdentityFields](Ash.Resource.Verifiers.VerifyIdentityFields.html) Raises an error on potentially incompatible identity attributes. [Ash.Resource.Verifiers.VerifyPrimaryKeyPresent](Ash.Resource.Verifiers.VerifyPrimaryKeyPresent.html) Raises an error when a required primary key is missing [Ash.Resource.Verifiers.VerifyReservedCalculationArguments](Ash.Resource.Verifiers.VerifyReservedCalculationArguments.html) Verifies that standard context keys are not used as calculation arguments [Ash.Resource.Verifiers.VerifySelectedByDefault](Ash.Resource.Verifiers.VerifySelectedByDefault.html) Raises an error when a required primary key is missing [Ash.SatSolver](Ash.SatSolver.html) Tools for working with the satsolver that drives filter subset checking (for authorization) [Ash.Seed](Ash.Seed.html) Helpers for seeding data, useful for quickly creating lots of data either for database seeding or testing. [Ash.Sort](Ash.Sort.html) Utilities and types for sorting. [Ash.Test](Ash.Test.html) Testing helpers for Ash. [Ash.ToTenant](Ash.ToTenant.html) Converts a value to a tenant. To add this to a resource, implement the protocol like so:application [Ash.Tracer](Ash.Tracer.html) A behaviour for implementing tracing for an Ash application. [Ash.Tracer.Simple](Ash.Tracer.Simple.html) A simple tracer that can send traces to the current process or call a module with the trace. [Ash.Tracer.Simple.Span](Ash.Tracer.Simple.Span.html) A span produced by [`Ash.Tracer.Simple`](Ash.Tracer.Simple.html) [Ash.Type](Ash.Type.html) The [`Ash.Type`](Ash.Type.html) behaviour is used to define a value type in Ash. [Ash.Type.Atom](Ash.Type.Atom.html) Stores an atom as a string in the database [Ash.Type.Binary](Ash.Type.Binary.html) Represents a binary. [Ash.Type.Boolean](Ash.Type.Boolean.html) Represents a boolean. [Ash.Type.CiString](Ash.Type.CiString.html) Stores a case insensitive string in the database [Ash.Type.Comparable](Ash.Type.Comparable.html) Helpers for working with [`Comparable`](Comparable.html) [Ash.Type.Date](Ash.Type.Date.html) Represents a date in the database [Ash.Type.DateTime](Ash.Type.DateTime.html) Represents a datetime, with configurable precision and timezone. [Ash.Type.Decimal](Ash.Type.Decimal.html) Represents a decimal. [Ash.Type.DurationName](Ash.Type.DurationName.html) An interval of time, primarily meant to be used in expression functions [Ash.Type.Enum](Ash.Type.Enum.html) A type for abstracting enums into a single type. [Ash.Type.File](Ash.Type.File.html) A type that represents a file on the filesystem. [Ash.Type.File.Implementation](Ash.Type.File.Implementation.html) Behaviour for file implementations that are compatible with [`Ash.Type.File`](Ash.Type.File.html). [Ash.Type.File.Source](Ash.Type.File.Source.html) Protocol for allowing the casting of something into an [`Ash.Type.File`](Ash.Type.File.html). [Ash.Type.Float](Ash.Type.Float.html) Represents a float (floating point number) [Ash.Type.Function](Ash.Type.Function.html) Represents a function. [Ash.Type.Integer](Ash.Type.Integer.html) Represents a simple integer [Ash.Type.Keyword](Ash.Type.Keyword.html) Represents a keyword list, stored as a `:map` in the database. [Ash.Type.Map](Ash.Type.Map.html) Represents a map stored in the database. [Ash.Type.Module](Ash.Type.Module.html) Stores a module as a string in the database. [Ash.Type.NaiveDatetime](Ash.Type.NaiveDatetime.html) Represents a Naive datetime [Ash.Type.NewType](Ash.Type.NewType.html) Allows defining a new type that is the combination of an existing type and custom constraints [Ash.Type.String](Ash.Type.String.html) Stores a string in the database. [Ash.Type.Struct](Ash.Type.Struct.html) Represents a struct. [Ash.Type.Term](Ash.Type.Term.html) Represents a raw elixir term in the database [Ash.Type.Time](Ash.Type.Time.html) Represents a time in the database [Ash.Type.UUID](Ash.Type.UUID.html) Represents a UUID. [Ash.Type.UUIDv7](Ash.Type.UUIDv7.html) Represents a UUID. [Ash.Type.Union](Ash.Type.Union.html) A union between multiple types, distinguished with a tag or by attempting to validate. [Ash.Type.UrlEncodedBinary](Ash.Type.UrlEncodedBinary.html) Represents a binary that attempts to decode input strings as a url encoded base64 string. [Ash.Type.UtcDatetime](Ash.Type.UtcDatetime.html) Represents a utc datetime. A wrapper around `:datetime` for backwards compatibility. [Ash.Type.UtcDatetimeUsec](Ash.Type.UtcDatetimeUsec.html) Represents a utc datetime with `nanosecond` precision. A wrapper around `:datetime` for backwards compatibility. [Ash.Type.Vector](Ash.Type.Vector.html) Represents a vector. [Ash.UUID](Ash.UUID.html) Helpers for working with UUIDs [Ash.UUIDv7](Ash.UUIDv7.html) Helpers for working with UUIDs version 7. [Ash.Union](Ash.Union.html) A wrapper for values that are sourced from [`Ash.Type.Union`](Ash.Type.Union.html). [Ash.Vector](Ash.Vector.html) A vector struct for Ash. [Comp](Comp.html) Provides utilities to implement and work with [`Comparable`](Comparable.html) types [Comparable](Comparable.html) Protocol which describes ordering relation for pair of types [Comparable.Type.Any.To.Any](Comparable.Type.Any.To.Any.html) [Comparable.Type.Ash.CiString.To.Ash.CiString](Comparable.Type.Ash.CiString.To.Ash.CiString.html) [Comparable.Type.Ash.CiString.To.BitString](Comparable.Type.Ash.CiString.To.BitString.html) [Comparable.Type.Atom.To.BitString](Comparable.Type.Atom.To.BitString.html) [Comparable.Type.BitString.To.Ash.CiString](Comparable.Type.BitString.To.Ash.CiString.html) [Comparable.Type.BitString.To.Atom](Comparable.Type.BitString.To.Atom.html) [Comparable.Type.BitString.To.Decimal](Comparable.Type.BitString.To.Decimal.html) [Comparable.Type.Date.To.Date](Comparable.Type.Date.To.Date.html) [Comparable.Type.DateTime.To.DateTime](Comparable.Type.DateTime.To.DateTime.html) [Comparable.Type.Decimal.To.BitString](Comparable.Type.Decimal.To.BitString.html) [Comparable.Type.Decimal.To.Decimal](Comparable.Type.Decimal.To.Decimal.html) [Comparable.Type.Decimal.To.Float](Comparable.Type.Decimal.To.Float.html) [Comparable.Type.Decimal.To.Integer](Comparable.Type.Decimal.To.Integer.html) [Comparable.Type.Float.To.Decimal](Comparable.Type.Float.To.Decimal.html) [Comparable.Type.Integer.To.Decimal](Comparable.Type.Integer.To.Decimal.html) [Comparable.Type.List.To.List](Comparable.Type.List.To.List.html) [Comparable.Type.Map.To.Map](Comparable.Type.Map.To.Map.html) [Comparable.Type.NaiveDateTime.To.NaiveDateTime](Comparable.Type.NaiveDateTime.To.NaiveDateTime.html) [Comparable.Type.Time.To.Time](Comparable.Type.Time.To.Time.html) [Comparable.Type.Tuple.To.Tuple](Comparable.Type.Tuple.To.Tuple.html) ## [](api-reference.html#mix-tasks)Mix Tasks [mix ash.codegen](Mix.Tasks.Ash.Codegen.html) Runs all codegen tasks for any extension on any resource/domain in your application. [mix ash.gen.base\_resource](Mix.Tasks.Ash.Gen.BaseResource.html) Generates a base resource [mix ash.gen.domain](Mix.Tasks.Ash.Gen.Domain.html) Generates an Ash.Domain [mix ash.gen.enum](Mix.Tasks.Ash.Gen.Enum.html) Generates an Ash.Type.Enum [mix ash.gen.resource](Mix.Tasks.Ash.Gen.Resource.html) Generate and configure an Ash.Resource. [mix ash.generate\_livebook](Mix.Tasks.Ash.GenerateLivebook.html) Generates a Livebook for each Ash domain. [mix ash.generate\_policy\_charts](Mix.Tasks.Ash.GeneratePolicyCharts.html) Generates a Mermaid Flow Chart for a given resource's policies. [mix ash.generate\_resource\_diagrams](Mix.Tasks.Ash.GenerateResourceDiagrams.html) Generates a Mermaid Resource Diagram for each Ash domain. [mix ash.install](Mix.Tasks.Ash.Install.html) Installs Ash into a project. Should be called with `mix igniter.install ash` [mix ash.migrate](Mix.Tasks.Ash.Migrate.html) Runs all migration tasks for any extension on any resource/domain in your application. [mix ash.patch.extend](Mix.Tasks.Ash.Patch.Extend.html) Adds an extension or extensions to the domain/resource [mix ash.reset](Mix.Tasks.Ash.Reset.html) Runs all tear down tasks for any extension on any resource/domain in your application, followed by setup tasks. [mix ash.rollback](Mix.Tasks.Ash.Rollback.html) Runs all rollback tasks for any extension on any resource/domain in your application. [mix ash.setup](Mix.Tasks.Ash.Setup.html) Runs all setup tasks for any extension on any resource/domain in your application. [mix ash.tear\_down](Mix.Tasks.Ash.TearDown.html) Runs all tear down tasks for any extension on any resource/domain in your application. [Next Page → Home](readme.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.ActionInput (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L1 "View Source") Input for a custom action # [](Ash.ActionInput.html#summary)Summary ## [Types](Ash.ActionInput.html#types) [t()](Ash.ActionInput.html#t:t/0) ## [Functions](Ash.ActionInput.html#functions) [add\_error(input, errors, path \\\\ \[\])](Ash.ActionInput.html#add_error/3) Add an error to the errors list and mark the action input as invalid. [fetch\_argument(input, argument)](Ash.ActionInput.html#fetch_argument/2) Fetches the value of an argument provided to the input or `:error`. [for\_action(resource\_or\_input, action, params, opts \\\\ \[\])](Ash.ActionInput.html#for_action/4) Creates a new input for a generic action [get\_argument(input, argument)](Ash.ActionInput.html#get_argument/2) Gets the value of an argument provided to the input. [new(resource, domain \\\\ nil)](Ash.ActionInput.html#new/2) [set\_argument(input, argument, value)](Ash.ActionInput.html#set_argument/3) Set an argument value [set\_context(input, map)](Ash.ActionInput.html#set_context/2) Deep merges the provided map into the input context that can be used later [set\_private\_argument(input, name, value)](Ash.ActionInput.html#set_private_argument/3) Sets a private argument value [set\_tenant(input, tenant)](Ash.ActionInput.html#set_tenant/2) # [](Ash.ActionInput.html#types)Types [](Ash.ActionInput.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L23) ``` @type t() :: %Ash.ActionInput{ action: Ash.Resource.Actions.Action.t() | nil, arguments: map(), context: map(), domain: Ash.Domain.t(), errors: term(), invalid_keys: MapSet.t(), params: map(), resource: Ash.Resource.t(), tenant: term(), valid?: boolean() } ``` # [](Ash.ActionInput.html#functions)Functions [](Ash.ActionInput.html#add_error/3) # add\_error(input, errors, path \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L406) ``` @spec add_error( t(), Ash.Error.error_input() | [Ash.Error.error_input()], Ash.Error.path_input() ) :: t() ``` Add an error to the errors list and mark the action input as invalid. See [`Ash.Error.to_ash_error/3`](Ash.Error.html#to_ash_error/3) for more on supported values for `error` [](Ash.ActionInput.html#fetch_argument/2) # fetch\_argument(input, argument) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L202) ``` @spec fetch_argument(t(), atom() | String.t()) :: {:ok, term()} | :error ``` Fetches the value of an argument provided to the input or `:error`. [](Ash.ActionInput.html#for_action/4) # for\_action(resource\_or\_input, action, params, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L97) ``` @spec for_action( resource_or_input :: Ash.Resource.t() | t(), action :: atom(), params :: map(), opts :: Keyword.t() ) :: t() ``` Creates a new input for a generic action ## [](Ash.ActionInput.html#for_action/4-options)Options - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use for the action. The resource's domain is used by default. - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the action input. The default value is `%{}`. - `:authorize?` - Whether or not to run authorization on the action. Default behavior of this option is controlled by the domain. - `:tenant` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The tenant to use for the action. - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The actor performing the action - `:skip_unknown_inputs` - A list of unknow inputs to skip. Use `:*` to skip all unknown inputs. - `:tracer` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A tracer or list of tracers to trace action execution. - `:private_arguments` ([`map/0`](../elixir/typespecs.html#basic-types)) - A list of private arguments to be set before the action is invoked. The default value is `%{}`. [](Ash.ActionInput.html#get_argument/2) # get\_argument(input, argument) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L193) ``` @spec get_argument(t(), atom() | String.t()) :: term() ``` Gets the value of an argument provided to the input. [](Ash.ActionInput.html#new/2) # new(resource, domain \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L34) [](Ash.ActionInput.html#set_argument/3) # set\_argument(input, argument, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L210) ``` @spec set_argument(input :: t(), name :: atom(), value :: term()) :: t() ``` Set an argument value [](Ash.ActionInput.html#set_context/2) # set\_context(input, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L289) ``` @spec set_context(t(), map() | nil) :: t() ``` Deep merges the provided map into the input context that can be used later Do not use the `private` key in your custom context, as that is reserved for internal use. [](Ash.ActionInput.html#set_private_argument/3) # set\_private\_argument(input, name, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L259) ``` @spec set_private_argument(input :: t(), name :: atom(), value :: term()) :: t() ``` Sets a private argument value [](Ash.ActionInput.html#set_tenant/2) # set\_tenant(input, tenant) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/action_input.ex#L140) ``` @spec set_tenant(t(), Ash.ToTenant.t()) :: t() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Actions.Read.AsyncLimiter (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/actions/read/async_limiter.ex#L1 "View Source") A utility for limiting the number of concurrent async operations Because this is an optimization, we opt to run something synchronously if there is no async task available in the slot. The idea here is that the *vast* majority of things we do async will be fast enough not to warrant always waiting for an async slot to be free. We may add in some smarter heuristics later (i.e choosing to wait for a task instead of doing the work sync), but for now this is a good start. # [](Ash.Actions.Read.AsyncLimiter.html#summary)Summary ## [Functions](Ash.Actions.Read.AsyncLimiter.html#functions) [async\_or\_inline(query, opts, last?, func)](Ash.Actions.Read.AsyncLimiter.html#async_or_inline/4) [await\_all(list)](Ash.Actions.Read.AsyncLimiter.html#await_all/1) [await\_at\_least\_one(list)](Ash.Actions.Read.AsyncLimiter.html#await_at_least_one/1) [child\_spec(arg)](Ash.Actions.Read.AsyncLimiter.html#child_spec/1) Returns a specification to start this module under a supervisor. [start\_link(limit)](Ash.Actions.Read.AsyncLimiter.html#start_link/1) # [](Ash.Actions.Read.AsyncLimiter.html#functions)Functions [](Ash.Actions.Read.AsyncLimiter.html#async_or_inline/4) # async\_or\_inline(query, opts, last?, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/actions/read/async_limiter.ex#L18) [](Ash.Actions.Read.AsyncLimiter.html#await_all/1) # await\_all(list) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/actions/read/async_limiter.ex#L62) [](Ash.Actions.Read.AsyncLimiter.html#await_at_least_one/1) # await\_at\_least\_one(list) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/actions/read/async_limiter.ex#L73) [](Ash.Actions.Read.AsyncLimiter.html#child_spec/1) # child\_spec(arg) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/actions/read/async_limiter.ex#L12) Returns a specification to start this module under a supervisor. See [`Supervisor`](../elixir/Supervisor.html). [](Ash.Actions.Read.AsyncLimiter.html#start_link/1) # start\_link(limit) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/actions/read/async_limiter.ex#L14) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Authorizer behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L1 "View Source") The interface for an ash authorizer These will typically be implemented by an extension, but a custom one can be implemented by defining an extension that also adopts this behaviour. Then you can extend a resource with `authorizers: [YourAuthorizer]` # [](Ash.Authorizer.html#summary)Summary ## [Types](Ash.Authorizer.html#types) [context()](Ash.Authorizer.html#t:context/0) [state()](Ash.Authorizer.html#t:state/0) ## [Callbacks](Ash.Authorizer.html#callbacks) [add\_calculations(arg1, state, context)](Ash.Authorizer.html#c:add_calculations/3) [alter\_filter(filter, state, context)](Ash.Authorizer.html#c:alter_filter/3) [alter\_results(state, list, context)](Ash.Authorizer.html#c:alter_results/3) [check(state, context)](Ash.Authorizer.html#c:check/2) [check\_context(state)](Ash.Authorizer.html#c:check_context/1) [exception(atom, state)](Ash.Authorizer.html#c:exception/2) [initial\_state(t, record, action, t)](Ash.Authorizer.html#c:initial_state/4) [strict\_check(state, context)](Ash.Authorizer.html#c:strict_check/2) [strict\_check\_context(state)](Ash.Authorizer.html#c:strict_check_context/1) ## [Functions](Ash.Authorizer.html#functions) [add\_calculations(module, query\_or\_changeset, state, context)](Ash.Authorizer.html#add_calculations/4) [alter\_filter(module, state, filter, context)](Ash.Authorizer.html#alter_filter/4) [alter\_results(module, state, records, context)](Ash.Authorizer.html#alter_results/4) [alter\_sort(module, state, sort, context)](Ash.Authorizer.html#alter_sort/4) [check(module, state, context)](Ash.Authorizer.html#check/3) [check\_context(module, state)](Ash.Authorizer.html#check_context/2) [exception(module, reason, state)](Ash.Authorizer.html#exception/3) [initial\_state(module, actor, resource, action, domain)](Ash.Authorizer.html#initial_state/5) [strict\_check(module, state, context)](Ash.Authorizer.html#strict_check/3) [strict\_check\_context(module, state)](Ash.Authorizer.html#strict_check_context/2) # [](Ash.Authorizer.html#types)Types [](Ash.Authorizer.html#t:context/0) # context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L11) ``` @type context() :: map() ``` [](Ash.Authorizer.html#t:state/0) # state() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L10) ``` @type state() :: map() ``` # [](Ash.Authorizer.html#callbacks)Callbacks [](Ash.Authorizer.html#c:add_calculations/3) # add\_calculations(arg1, state, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L28) ``` @callback add_calculations(Ash.Query.t() | Ash.Changeset.t(), state(), context()) :: {:ok, Ash.Query.t() | Ash.Changeset.t(), state()} | {:error, Ash.Error.t()} ``` [](Ash.Authorizer.html#c:alter_filter/3) # alter\_filter(filter, state, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L26) ``` @callback alter_filter(filter :: Ash.Filter.t(), state(), context()) :: {:ok, Ash.Filter.t()} | {:error, Ash.Error.t()} ``` [](Ash.Authorizer.html#c:alter_results/3) # alter\_results(state, list, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L30) ``` @callback alter_results(state(), [Ash.Resource.record()], context()) :: {:ok, [Ash.Resource.record()]} | {:error, Ash.Error.t()} ``` [](Ash.Authorizer.html#c:check/2) # check(state, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L33) ``` @callback check(state(), context()) :: :authorized | {:data, [Ash.Resource.record()]} | {:error, :forbidden, state()} | {:error, Ash.Error.t()} ``` [](Ash.Authorizer.html#c:check_context/1) # check\_context(state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L32) ``` @callback check_context(state()) :: [atom()] ``` [](Ash.Authorizer.html#c:exception/2) # exception(atom, state) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L38) ``` @callback exception(atom(), state()) :: no_return() ``` [](Ash.Authorizer.html#c:initial_state/4) # initial\_state(t, record, action, t) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L12) ``` @callback initial_state( Ash.Resource.t(), Ash.Resource.record(), Ash.Resource.Actions.action(), Ash.Domain.t() ) :: state() ``` [](Ash.Authorizer.html#c:strict_check/2) # strict\_check(state, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L19) ``` @callback strict_check(state(), context()) :: {:authorized, state()} | {:continue, state()} | {:filter, Keyword.t()} | {:filter, Keyword.t(), state()} | {:filter_and_continue, Keyword.t(), state()} | {:error, term()} ``` [](Ash.Authorizer.html#c:strict_check_context/1) # strict\_check\_context(state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L18) ``` @callback strict_check_context(state()) :: [atom()] ``` # [](Ash.Authorizer.html#functions)Functions [](Ash.Authorizer.html#add_calculations/4) # add\_calculations(module, query\_or\_changeset, state, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L72) [](Ash.Authorizer.html#alter_filter/4) # alter\_filter(module, state, filter, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L88) [](Ash.Authorizer.html#alter_results/4) # alter\_results(module, state, records, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L80) [](Ash.Authorizer.html#alter_sort/4) # alter\_sort(module, state, sort, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L96) [](Ash.Authorizer.html#check/3) # check(module, state, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L108) [](Ash.Authorizer.html#check_context/2) # check\_context(module, state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L104) [](Ash.Authorizer.html#exception/3) # exception(module, reason, state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L52) [](Ash.Authorizer.html#initial_state/5) # initial\_state(module, actor, resource, action, domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L48) [](Ash.Authorizer.html#strict_check/3) # strict\_check(module, state, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L68) [](Ash.Authorizer.html#strict_check_context/2) # strict\_check\_context(module, state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/authorizer.ex#L64) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.BulkResult (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/bulk_result.ex#L1 "View Source") The return value for bulk actions. # [](Ash.BulkResult.html#summary)Summary ## [Types](Ash.BulkResult.html#types) [t()](Ash.BulkResult.html#t:t/0) # [](Ash.BulkResult.html#types)Types [](Ash.BulkResult.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/bulk_result.ex#L6) ``` @type t() :: %Ash.BulkResult{ error_count: non_neg_integer(), errors: [Ash.Error.t() | Ash.Changeset.t()] | nil, notifications: [Ash.Notifier.Notification.t()] | nil, records: [Ash.Resource.record()] | nil, status: :success | :partial_success | :error } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Can (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/can.ex#L1 "View Source") Contains the Ash.can function logic. # [](Ash.Can.html#summary)Summary ## [Types](Ash.Can.html#types) [subject()](Ash.Can.html#t:subject/0) ## [Functions](Ash.Can.html#functions) [can(action\_or\_query\_or\_changeset, domain, actor, opts \\\\ \[\])](Ash.Can.html#can/4) Returns a an ok tuple if the actor can perform the action, query, or changeset, an error tuple if an error happens, and a ok tuple with maybe if maybe is set to true or not set. [can?(action\_or\_query\_or\_changeset, domain, actor, opts \\\\ \[\])](Ash.Can.html#can?/4) Returns whether an actor can perform an action, query, or changeset. # [](Ash.Can.html#types)Types [](Ash.Can.html#t:subject/0) # subject() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/can.ex#L8) ``` @type subject() :: Ash.Query.t() | Ash.Changeset.t() | Ash.ActionInput.t() | {Ash.Resource.t(), atom() | Ash.Resource.Actions.action()} | {Ash.Resource.t(), atom() | Ash.Resource.Actions.action(), input :: map()} | {Ash.Resource.record(), atom() | Ash.Resource.Actions.action()} | {Ash.Resource.record(), atom() | Ash.Resource.Actions.action(), input :: map()} ``` # [](Ash.Can.html#functions)Functions [](Ash.Can.html#can/4) # can(action\_or\_query\_or\_changeset, domain, actor, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/can.ex#L68) ``` @spec can(subject(), Ash.Domain.t(), Ash.Resource.record(), Keyword.t()) :: {:ok, boolean() | :maybe} | {:ok, boolean(), term()} | {:ok, boolean(), Ash.Changeset.t(), Ash.Query.t()} | {:error, Ash.Error.t()} ``` Returns a an ok tuple if the actor can perform the action, query, or changeset, an error tuple if an error happens, and a ok tuple with maybe if maybe is set to true or not set. You should prefer to use [`Ash.can/3`](Ash.html#can/3) over this module, directly. Note: `is_maybe` is set to `true`, if not set. [](Ash.Can.html#can?/4) # can?(action\_or\_query\_or\_changeset, domain, actor, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/can.ex#L26) ``` @spec can?(subject(), Ash.Domain.t(), Ash.Resource.record(), Keyword.t()) :: boolean() | no_return() ``` Returns whether an actor can perform an action, query, or changeset. You should prefer to use [`Ash.can?/3`](Ash.html#can?/3) over this module, directly. Can raise an exception if return\_forbidden\_error is truthy in opts or there's an error. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Changeset (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1 "View Source") Changesets are used to create and update data in Ash. Create a changeset with [`new/1`](Ash.Changeset.html#new/1) or `new/2`, and alter the attributes and relationships using the functions provided in this module. Nothing in this module actually incurs changes in a data layer. To commit a changeset, see [`Ash.create/2`](Ash.html#create/2) and [`Ash.update/2`](Ash.html#update/2). # Changeset lifecycle ## [](Ash.Changeset.html#module-action-lifecycle)Action Lifecycle The following example illustrates the hook lifecycle of a changeset. ``` defmodule AshChangesetLifeCycleExample do def change(changeset, _, _) do changeset # execute code both before and after the transaction |> Ash.Changeset.around_transaction(fn changeset, callback -> callback.(changeset) end) # execute code before the transaction is started. Use for things like external calls |> Ash.Changeset.before_transaction(fn changeset -> changeset end) # execute code in the transaction, before and after the data layer is called |> Ash.Changeset.around_action(fn changeset, callback -> callback.(changeset) end) # execute code in the transaction, before the data layer is called |> Ash.Changeset.before_action(fn changeset -> changeset end) # execute code in the transaction, after the data layer is called, only if the action is successful |> Ash.Changeset.after_action(fn changeset, result -> {:ok, result} end) # execute code after the transaction, both in success and error cases |> Ash.Changeset.after_transaction(fn changeset, success_or_error_result -> success_or_error_result end end end ``` # [](Ash.Changeset.html#summary)Summary ## [Types](Ash.Changeset.html#types) [after\_action\_fun()](Ash.Changeset.html#t:after_action_fun/0) [after\_transaction\_fun()](Ash.Changeset.html#t:after_transaction_fun/0) [around\_action\_callback()](Ash.Changeset.html#t:around_action_callback/0) [around\_action\_fun()](Ash.Changeset.html#t:around_action_fun/0) [around\_action\_result()](Ash.Changeset.html#t:around_action_result/0) [around\_transaction\_callback()](Ash.Changeset.html#t:around_transaction_callback/0) [around\_transaction\_fun()](Ash.Changeset.html#t:around_transaction_fun/0) [around\_transaction\_result()](Ash.Changeset.html#t:around_transaction_result/0) [before\_action\_fun()](Ash.Changeset.html#t:before_action_fun/0) [before\_transaction\_fun()](Ash.Changeset.html#t:before_transaction_fun/0) [error\_info()](Ash.Changeset.html#t:error_info/0) [manage\_relationship\_type()](Ash.Changeset.html#t:manage_relationship_type/0) [phase()](Ash.Changeset.html#t:phase/0) [t()](Ash.Changeset.html#t:t/0) ## [Functions](Ash.Changeset.html#functions) [accessing(changeset, types \\\\ \[:attributes, :relationships, :calculations, :attributes\], only\_public? \\\\ true)](Ash.Changeset.html#accessing/3) Returns a list of attributes, aggregates, relationships, and calculations that are being loaded [add\_error(changeset, errors, path \\\\ \[\])](Ash.Changeset.html#add_error/3) Add an error to the errors list and mark the changeset as invalid. [after\_action(changeset, func, opts \\\\ \[\])](Ash.Changeset.html#after_action/3) Adds an after\_action hook to the changeset. [after\_transaction(changeset, func, opts \\\\ \[\])](Ash.Changeset.html#after_transaction/3) Adds an after\_transaction hook to the changeset. Cannot be called within other hooks. [apply\_attributes(changeset, opts \\\\ \[\])](Ash.Changeset.html#apply_attributes/2) Returns the original data with attribute changes merged, if the changeset is valid. [around\_action(changeset, func)](Ash.Changeset.html#around_action/2) Adds an around\_action hook to the changeset. [around\_transaction(changeset, func)](Ash.Changeset.html#around_transaction/2) Adds an around\_transaction hook to the changeset. [atomic\_ref(changeset, field)](Ash.Changeset.html#atomic_ref/2) Gets a reference to a field, or the current atomic update expression of that field. [atomic\_update(changeset, atomics)](Ash.Changeset.html#atomic_update/2) Adds multiple atomic changes to the changeset [atomic\_update(changeset, key, value)](Ash.Changeset.html#atomic_update/3) Adds an atomic change to the changeset. [attribute\_present?(changeset, attribute)](Ash.Changeset.html#attribute_present?/2) Checks if an attribute is not nil, either in the original data, or that it is not being changed to a `nil` value if it is changing. [before\_action(changeset, func, opts \\\\ \[\])](Ash.Changeset.html#before_action/3) Adds a before\_action hook to the changeset. [before\_transaction(changeset, func, opts \\\\ \[\])](Ash.Changeset.html#before_transaction/3) Adds a before\_transaction hook to the changeset. [change\_attribute(changeset, attribute, value)](Ash.Changeset.html#change_attribute/3) Adds a change to the changeset, unless the value matches the existing value. [change\_attributes(changeset, changes)](Ash.Changeset.html#change_attributes/2) Calls [`change_attribute/3`](Ash.Changeset.html#change_attribute/3) for each key/value pair provided. [change\_default\_attribute(changeset, attribute, value)](Ash.Changeset.html#change_default_attribute/3) The same as `change_attribute`, but annotates that the attribute is currently holding a default value. [change\_new\_attribute(changeset, attribute, value)](Ash.Changeset.html#change_new_attribute/3) Change an attribute only if is not currently being changed [change\_new\_attribute\_lazy(changeset, attribute, func)](Ash.Changeset.html#change_new_attribute_lazy/3) Change an attribute if is not currently being changed, by calling the provided function. [changing\_attribute?(changeset, attribute)](Ash.Changeset.html#changing_attribute?/2) Returns true if an attribute exists in the changes [changing\_attributes?(changeset)](Ash.Changeset.html#changing_attributes?/1) Returns true if any attributes on the resource are being changed. [changing\_relationship?(changeset, relationship)](Ash.Changeset.html#changing_relationship?/2) Returns true if a relationship exists in the changes [clear\_change(changeset, field)](Ash.Changeset.html#clear_change/2) Clears an attribute or relationship change off of the changeset. [delete\_argument(changeset, argument\_or\_arguments)](Ash.Changeset.html#delete_argument/2) Remove an argument from the changeset [deselect(changeset, fields)](Ash.Changeset.html#deselect/2) Ensure the the specified attributes are `nil` in the changeset results. [ensure\_selected(changeset, fields)](Ash.Changeset.html#ensure_selected/2) Ensures that the given attributes are selected. [expand\_upsert\_fields(fields, resource)](Ash.Changeset.html#expand_upsert_fields/2) Turns the special case {:replace, fields}, :replace\_all and {:replace\_all\_except, fields} upsert\_fields options into a list of fields [fetch\_argument(changeset, argument)](Ash.Changeset.html#fetch_argument/2) Fetches the value of an argument provided to the changeset or `:error`. [fetch\_argument\_or\_change(changeset, attribute)](Ash.Changeset.html#fetch_argument_or_change/2) Gets the value of an argument provided to the changeset, falling back to [`Ash.Changeset.fetch_change/2`](Ash.Changeset.html#fetch_change/2) if nothing was provided. [fetch\_change(changeset, attribute)](Ash.Changeset.html#fetch_change/2) Gets the new value for an attribute, or `:error` if it is not being changed. [filter(changeset, expr)](Ash.Changeset.html#filter/2) Adds a filter for a record being updated or destroyed. [for\_action(initial, action, params \\\\ %{}, opts \\\\ \[\])](Ash.Changeset.html#for_action/4) Constructs a changeset for a given action, and validates it. [for\_create(initial, action, params \\\\ %{}, opts \\\\ \[\])](Ash.Changeset.html#for_create/4) Constructs a changeset for a given create action, and validates it. [for\_destroy(initial, action\_or\_name, params \\\\ %{}, opts \\\\ \[\])](Ash.Changeset.html#for_destroy/4) Constructs a changeset for a given destroy action, and validates it. [for\_update(initial, action, params \\\\ %{}, opts \\\\ \[\])](Ash.Changeset.html#for_update/4) Constructs a changeset for a given update action, and validates it. [force\_change\_attribute(changeset, attribute, value)](Ash.Changeset.html#force_change_attribute/3) Changes an attribute even if it isn't writable [force\_change\_attributes(changeset, changes)](Ash.Changeset.html#force_change_attributes/2) Calls [`force_change_attribute/3`](Ash.Changeset.html#force_change_attribute/3) for each key/value pair provided. [force\_change\_new\_attribute(changeset, attribute, value)](Ash.Changeset.html#force_change_new_attribute/3) Force change an attribute if it is not currently being changed. [force\_change\_new\_attribute\_lazy(changeset, attribute, func)](Ash.Changeset.html#force_change_new_attribute_lazy/3) Force change an attribute if it is not currently being changed, by calling the provided function. [force\_delete\_argument(changeset, argument\_or\_arguments)](Ash.Changeset.html#force_delete_argument/2) Remove an argument from the changeset, not warning if the changeset has already been validated. [force\_set\_argument(changeset, argument, value)](Ash.Changeset.html#force_set_argument/3) Add an argument to the changeset, which will be provided to the action. [force\_set\_arguments(changeset, map)](Ash.Changeset.html#force_set_arguments/2) Merge a map of arguments to the arguments list. [fully\_atomic\_changeset(resource, action, params, opts \\\\ \[\])](Ash.Changeset.html#fully_atomic_changeset/4) [get\_argument(changeset, argument)](Ash.Changeset.html#get_argument/2) Gets the value of an argument provided to the changeset. [get\_argument\_or\_attribute(changeset, attribute)](Ash.Changeset.html#get_argument_or_attribute/2) Gets the value of an argument provided to the changeset, falling back to [`Ash.Changeset.get_attribute/2`](Ash.Changeset.html#get_attribute/2) if nothing was provided. [get\_attribute(changeset, attribute)](Ash.Changeset.html#get_attribute/2) Gets the changing value or the original value of an attribute. [get\_data(changeset, attribute)](Ash.Changeset.html#get_data/2) Gets the original value for an attribute [handle\_errors(changeset, func)](Ash.Changeset.html#handle_errors/2) Sets a custom error handler on the changeset. [handle\_params(changeset, action, params, handle\_params\_opts \\\\ \[\])](Ash.Changeset.html#handle_params/4) [is\_valid(changeset)](Ash.Changeset.html#is_valid/1) A guard which checks if the Changeset is valid. [load(changeset, load)](Ash.Changeset.html#load/2) Calls the provided load statement on the result of the action at the very end of the action. [loading?(changeset, path)](Ash.Changeset.html#loading?/2) Returns true if the field/relationship or path to field/relationship is being loaded. [manage\_relationship(changeset, relationship, input, opts \\\\ \[\])](Ash.Changeset.html#manage_relationship/4) Manages the related records by creating, updating, or destroying them as necessary. [manage\_relationship\_opts(atom)](Ash.Changeset.html#manage_relationship_opts/1) [new(record\_or\_resource)](Ash.Changeset.html#new/1) Returns a new changeset over a resource. [prepare\_changeset\_for\_action(changeset, action, opts)](Ash.Changeset.html#prepare_changeset_for_action/3) [present?(changeset, attribute)](Ash.Changeset.html#present?/2) Checks if an argument is not nil or an attribute is not nil, either in the original data, or that it is not being changed to a `nil` value if it is changing. [put\_context(changeset, key, value)](Ash.Changeset.html#put_context/3) Puts a key/value in the changeset context that can be used later. [run\_atomic\_change(changeset, map, context)](Ash.Changeset.html#run_atomic_change/3) [run\_before\_transaction\_hooks(changeset)](Ash.Changeset.html#run_before_transaction_hooks/1) [select(changeset, fields, opts \\\\ \[\])](Ash.Changeset.html#select/3) Ensure that only the specified attributes are present in the results. [selecting?(changeset, field)](Ash.Changeset.html#selecting?/2) [set\_argument(changeset, argument, value)](Ash.Changeset.html#set_argument/3) Add an argument to the changeset, which will be provided to the action. [set\_arguments(changeset, map)](Ash.Changeset.html#set_arguments/2) Merge a map of arguments to the arguments list. [set\_context(changeset, map)](Ash.Changeset.html#set_context/2) Deep merges the provided map into the changeset context that can be used later. [set\_on\_upsert(changeset, upsert\_keys)](Ash.Changeset.html#set_on_upsert/2) [set\_private\_argument(changeset, argument, value)](Ash.Changeset.html#set_private_argument/3) Add a private argument to the changeset, which will be provided to the action. [set\_result(changeset, result)](Ash.Changeset.html#set_result/2) Set the result of the action. This will prevent running the underlying datalayer behavior [set\_tenant(changeset, tenant)](Ash.Changeset.html#set_tenant/2) [timeout(changeset, timeout, default \\\\ nil)](Ash.Changeset.html#timeout/3) [update\_change(changeset, attribute, fun)](Ash.Changeset.html#update_change/3) Updates an existing attribute change by applying a function to it. [with\_hooks(changeset, func, opts \\\\ \[\])](Ash.Changeset.html#with_hooks/3) Wraps a function in the before/after action hooks of a changeset. # [](Ash.Changeset.html#types)Types [](Ash.Changeset.html#t:after_action_fun/0) # after\_action\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L216) ``` @type after_action_fun() :: (t(), Ash.Resource.record() -> {:ok, Ash.Resource.record()} | {:ok, Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | {:error, any()}) ``` [](Ash.Changeset.html#t:after_transaction_fun/0) # after\_transaction\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L222) ``` @type after_transaction_fun() :: (t(), {:ok, Ash.Resource.record()} | {:error, any()} -> {:ok, Ash.Resource.record()} | {:error, any()}) ``` [](Ash.Changeset.html#t:around_action_callback/0) # around\_action\_callback() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L233) ``` @type around_action_callback() :: (t() -> around_action_result()) ``` [](Ash.Changeset.html#t:around_action_fun/0) # around\_action\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L234) ``` @type around_action_fun() :: (t(), around_action_callback() -> around_action_result()) ``` [](Ash.Changeset.html#t:around_action_result/0) # around\_action\_result() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L230) ``` @type around_action_result() :: {:ok, Ash.Resource.record(), t(), %{notifications: [Ash.Notifier.Notification.t()]}} | {:error, Ash.Error.t()} ``` [](Ash.Changeset.html#t:around_transaction_callback/0) # around\_transaction\_callback() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L237) ``` @type around_transaction_callback() :: (t() -> around_transaction_result()) ``` [](Ash.Changeset.html#t:around_transaction_fun/0) # around\_transaction\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L238) ``` @type around_transaction_fun() :: (t(), around_transaction_callback() -> around_transaction_result()) ``` [](Ash.Changeset.html#t:around_transaction_result/0) # around\_transaction\_result() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L236) ``` @type around_transaction_result() :: {:ok, Ash.Resource.record()} | {:error, any()} ``` [](Ash.Changeset.html#t:before_action_fun/0) # before\_action\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L226) ``` @type before_action_fun() :: (t() -> t() | {t(), %{notifications: [Ash.Notifier.Notification.t()]}}) ``` [](Ash.Changeset.html#t:before_transaction_fun/0) # before\_transaction\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L228) ``` @type before_transaction_fun() :: (t() -> t()) ``` [](Ash.Changeset.html#t:error_info/0) # error\_info() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L293) ``` @type error_info() :: Ash.Error.error_input() ``` [](Ash.Changeset.html#t:manage_relationship_type/0) # manage\_relationship\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4267) ``` @type manage_relationship_type() :: :append_and_remove | :append | :remove | :direct_control | :create ``` [](Ash.Changeset.html#t:phase/0) # phase() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L252) ``` @type phase() :: :around_transaction | :around_action | :after_transaction | :before_transaction | :after_action | :before_action | :validate | :pending | :atomic ``` [](Ash.Changeset.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L254) ``` @type t() :: %Ash.Changeset{ __validated_for_action__: atom() | nil, action: Ash.Resource.Actions.action() | nil, action_failed?: boolean(), action_select: term(), action_type: Ash.Resource.Actions.action_type() | nil, added_filter: Ash.Filter.t() | nil, after_action: [after_action_fun() | {after_action_fun(), map()}], after_transaction: [ after_transaction_fun() | {after_transaction_fun(), map()} ], arguments: %{optional(atom()) => any()}, around_action: [around_action_fun() | {around_action_fun(), map()}], around_transaction: [ around_transaction_fun() | {around_transaction_fun(), map()} ], atomic_after_action: term(), atomic_changes: term(), atomic_validations: term(), atomics: Keyword.t(), attribute_changes: term(), attributes: %{optional(atom()) => any()}, before_action: [before_action_fun() | {before_action_fun(), map()}], before_transaction: [ before_transaction_fun() | {before_transaction_fun(), map()} ], casted_arguments: term(), casted_attributes: term(), context: map(), context_changes: term(), data: Ash.Resource.record() | nil, defaults: [atom()], dirty_hooks: term(), domain: module() | nil, errors: [Ash.Error.t()], filter: Ash.Filter.t() | nil, handle_errors: nil | (t(), error :: any() -> :ignore | t() | (error :: any()) | {error :: any(), t()}), invalid_keys: MapSet.t(), load: keyword(keyword()), no_atomic_constraints: term(), params: %{optional(atom() | binary()) => any()}, phase: phase(), relationships: %{ optional(atom()) => %{optional(atom() | binary()) => any()} | [%{optional(atom() | binary()) => any()}] }, resource: module(), select: [atom()] | nil, tenant: term(), timeout: pos_integer() | nil, to_tenant: term(), valid?: boolean() } ``` # [](Ash.Changeset.html#functions)Functions [](Ash.Changeset.html#accessing/3) # accessing(changeset, types \\\\ \[:attributes, :relationships, :calculations, :attributes], only\_public? \\\\ true) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L602) Returns a list of attributes, aggregates, relationships, and calculations that are being loaded Provide a list of field types to narrow down the returned results. [](Ash.Changeset.html#add_error/3) # add\_error(changeset, errors, path \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5978) ``` @spec add_error(t(), Ash.Error.error_input(), path :: Ash.Error.path_input()) :: t() ``` Add an error to the errors list and mark the changeset as invalid. See [`Ash.Error.to_ash_error/3`](Ash.Error.html#to_ash_error/3) for more on supported values for `error` [](Ash.Changeset.html#after_action/3) # after\_action(changeset, func, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5616) ``` @spec after_action( t(), after_action_fun(), Keyword.t() ) :: t() ``` Adds an after\_action hook to the changeset. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. [](Ash.Changeset.html#after_transaction/3) # after\_transaction(changeset, func, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5656) ``` @spec after_transaction( t(), after_transaction_fun(), Keyword.t() ) :: t() ``` Adds an after\_transaction hook to the changeset. Cannot be called within other hooks. `after_transaction` hooks differ from `after_action` hooks in that they are run on success *and* failure of the action or some previous hook. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. [](Ash.Changeset.html#apply_attributes/2) # apply\_attributes(changeset, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5838) ``` @spec apply_attributes(t(), opts :: Keyword.t()) :: {:ok, Ash.Resource.record()} | {:error, t()} ``` Returns the original data with attribute changes merged, if the changeset is valid. Options: - force? - applies current attributes even if the changeset is not valid [](Ash.Changeset.html#around_action/2) # around\_action(changeset, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5742) ``` @spec around_action(t(), around_action_fun()) :: t() ``` Adds an around\_action hook to the changeset. Your function will get the changeset, and a callback that must be called with a changeset (that may be modified). The callback will return `{:ok, result, changeset, instructions}` or `{:error, error}`. You can modify these values, but the return value must be one of those types. Instructions contains the notifications in its `notifications` key, i.e `%{notifications: [%Ash.Resource.Notification{}, ...]}`. The around\_action calls happen first, and then (after they each resolve their callbacks) the `before_action` hooks are called, followed by the action itself occurring at the data layer and then the `after_action` hooks being run. Then, the code that appeared *after* the callbacks were called is then run. For example: ``` changeset |> Ash.Changeset.around_action(fn changeset, callback -> IO.puts("first around: before") result = callback.(changeset) IO.puts("first around: after") result end) |> Ash.Changeset.around_action(fn changeset, callback -> IO.puts("second around: before") result = callback.(changeset) IO.puts("second around: after") result end) |> Ash.Changeset.before_action(fn changeset -> IO.puts("first before") changeset end) |> Ash.Changeset.before_action(fn changeset -> IO.puts("second before") changeset end) |> Ash.Changeset.after_action(fn changeset, result -> IO.puts("first after") {:ok, result} end) |> Ash.Changeset.after_action(fn changeset, result -> IO.puts("second after") {:ok, result} end) ``` This would print: ``` first around: before second around: before first before second before <-- action happens here first after second after second around: after <-- Notice that because of the callbacks, the after of the around hooks is reversed from the before first around: after ``` Warning: using this without understanding how it works can cause big problems. You *must* call the callback function that is provided to your hook, and the return value must contain the same structure that was given to you, i.e `{:ok, result_of_action, instructions}`. You can almost always get the same effect by using `before_action`, setting some context on the changeset and reading it out in an `after_action` hook. [](Ash.Changeset.html#around_transaction/2) # around\_transaction(changeset, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5817) ``` @spec around_transaction(t(), around_transaction_fun()) :: t() ``` Adds an around\_transaction hook to the changeset. Your function will get the changeset, and a callback that must be called with a changeset (that may be modified). The callback will return `{:ok, result}` or `{:error, error}`. You can modify these values, but the return value must be one of those types. The around\_transaction calls happen first, and then (after they each resolve their callbacks) the `before_transaction` hooks are called, followed by the action hooks and then the `after_transaction` hooks being run. Then, the code that appeared *after* the callbacks were called is then run. For example: ``` changeset |> Ash.Changeset.around_transaction(fn changeset, callback -> IO.puts("first around: before") result = callback.(changeset) IO.puts("first around: after") result end) |> Ash.Changeset.around_transaction(fn changeset, callback -> IO.puts("second around: before") result = callback.(changeset) IO.puts("second around: after") result end) |> Ash.Changeset.before_transaction(fn changeset -> IO.puts("first before") changeset end) |> Ash.Changeset.before_transaction(fn changeset -> IO.puts("second before") changeset end) |> Ash.Changeset.after_transaction(fn changeset, result -> IO.puts("first after") result end) |> Ash.Changeset.after_transaction(fn changeset, result -> IO.puts("second after") result end) ``` This would print: ``` first around: before second around: before first before second before <-- action hooks happens here first after second after second around: after <-- Notice that because of the callbacks, the after of the around hooks is reversed from the before first around: after ``` Warning: using this without understanding how it works can cause big problems. You *must* call the callback function that is provided to your hook, and the return value must contain the same structure that was given to you, i.e `{:ok, result_of_action}`. You can almost always get the same effect by using `before_transaction`, setting some context on the changeset and reading it out in an `after_transaction` hook. [](Ash.Changeset.html#atomic_ref/2) # atomic\_ref(changeset, field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1082) Gets a reference to a field, or the current atomic update expression of that field. [](Ash.Changeset.html#atomic_update/2) # atomic\_update(changeset, atomics) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1652) ``` @spec atomic_update(t(), map() | Keyword.t()) :: t() ``` Adds multiple atomic changes to the changeset See [`atomic_update/3`](Ash.Changeset.html#atomic_update/3) for more information. [](Ash.Changeset.html#atomic_update/3) # atomic\_update(changeset, key, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1699) ``` @spec atomic_update(t(), atom(), {:atomic, Ash.Expr.t()} | Ash.Expr.t()) :: t() ``` Adds an atomic change to the changeset. Atomic changes are applied by the data layer, and as such have guarantees that are not given by changes that are based on looking at the previous value and updating it. Here is an example of a change that is not safe to do concurrently: ``` change fn changeset, _ -> Ash.Changeset.change_attribute(changeset, :score, changeset.data.score + 1) end ``` If two processes run this concurrently, they will both read the same value of `score`, and set the new score to the same value. This means that one of the increments will be lost. If you were to instead do this using `atomic_update`, you would get the correct result: ``` Ash.Changeset.atomic_update(changeset, :score, expr(score + 1)) ``` There are drawbacks/things to consider, however. The first is that atomic update results are not known until after the action is run. The following functional validation would not be able to enforce the score being less than 10, because the atomic happens after the validation. ``` validate fn changeset, _ -> if Ash.Changeset.get_attribute(changeset, :score) < 10 do :ok else {:error, field: :score, message: "must be less than 10"} end end ``` If you want to use atomic updates, it is suggested to write module-based validations &amp; changes, and implement the appropriate atomic callbacks on those modules. All builtin validations and changes implement these callbacks in addition to the standard callbacks. Validations will only be run atomically when the entire action is being run atomically or if one of the relevant fields is being updated atomically. [](Ash.Changeset.html#attribute_present?/2) # attribute\_present?(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L2046) Checks if an attribute is not nil, either in the original data, or that it is not being changed to a `nil` value if it is changing. This also accounts for the `accessing_from` context that is set when using `manage_relationship`, so it is aware that a particular value *will* be set by `manage_relationship` even if it isn't currently being set. [](Ash.Changeset.html#before_action/3) # before\_action(changeset, func, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5574) ``` @spec before_action( changeset :: t(), fun :: before_action_fun(), opts :: Keyword.t() ) :: t() ``` Adds a before\_action hook to the changeset. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. [](Ash.Changeset.html#before_transaction/3) # before\_transaction(changeset, func, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5595) ``` @spec before_transaction( t(), before_transaction_fun(), Keyword.t() ) :: t() ``` Adds a before\_transaction hook to the changeset. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. [](Ash.Changeset.html#change_attribute/3) # change\_attribute(changeset, attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5364) ``` @spec change_attribute(t(), atom(), any()) :: t() ``` Adds a change to the changeset, unless the value matches the existing value. [](Ash.Changeset.html#change_attributes/2) # change\_attributes(changeset, changes) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5354) ``` @spec change_attributes(t(), map() | Keyword.t()) :: t() ``` Calls [`change_attribute/3`](Ash.Changeset.html#change_attribute/3) for each key/value pair provided. [](Ash.Changeset.html#change_default_attribute/3) # change\_default\_attribute(changeset, attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5476) ``` @spec change_default_attribute(t(), atom(), any()) :: t() ``` The same as `change_attribute`, but annotates that the attribute is currently holding a default value. This information can be used in changes to see if a value was explicitly set or if it was set by being the default. Additionally, this is used in `upsert` actions to not overwrite existing values with the default. [](Ash.Changeset.html#change_new_attribute/3) # change\_new\_attribute(changeset, attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5102) ``` @spec change_new_attribute(t(), atom(), term()) :: t() ``` Change an attribute only if is not currently being changed [](Ash.Changeset.html#change_new_attribute_lazy/3) # change\_new\_attribute\_lazy(changeset, attribute, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5119) ``` @spec change_new_attribute_lazy(t(), atom(), (-> any())) :: t() ``` Change an attribute if is not currently being changed, by calling the provided function. Use this if you want to only perform some expensive calculation for an attribute value only if there isn't already a change for that attribute. [](Ash.Changeset.html#changing_attribute?/2) # changing\_attribute?(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5089) ``` @spec changing_attribute?(t(), atom()) :: boolean() ``` Returns true if an attribute exists in the changes [](Ash.Changeset.html#changing_attributes?/1) # changing\_attributes?(changeset) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5081) ``` @spec changing_attributes?(t()) :: boolean() ``` Returns true if any attributes on the resource are being changed. [](Ash.Changeset.html#changing_relationship?/2) # changing\_relationship?(changeset, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5096) ``` @spec changing_relationship?(t(), atom()) :: boolean() ``` Returns true if a relationship exists in the changes [](Ash.Changeset.html#clear_change/2) # clear\_change(changeset, field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5862) Clears an attribute or relationship change off of the changeset. [](Ash.Changeset.html#delete_argument/2) # delete\_argument(changeset, argument\_or\_arguments) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5283) Remove an argument from the changeset [](Ash.Changeset.html#deselect/2) # deselect(changeset, fields) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L546) Ensure the the specified attributes are `nil` in the changeset results. [](Ash.Changeset.html#ensure_selected/2) # ensure\_selected(changeset, fields) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L533) Ensures that the given attributes are selected. The first call to [`select/2`](Ash.Changeset.html#select/2) will *limit* the fields to only the provided fields. Use [`ensure_selected/2`](Ash.Changeset.html#ensure_selected/2) to say "select this field (or these fields) without deselecting anything else". See [`select/2`](Ash.Changeset.html#select/2) for more. [](Ash.Changeset.html#expand_upsert_fields/2) # expand\_upsert\_fields(fields, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1822) Turns the special case {:replace, fields}, :replace\_all and {:replace\_all\_except, fields} upsert\_fields options into a list of fields [](Ash.Changeset.html#fetch_argument/2) # fetch\_argument(changeset, argument) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4159) ``` @spec fetch_argument(t(), atom()) :: {:ok, term()} | :error ``` Fetches the value of an argument provided to the changeset or `:error`. [](Ash.Changeset.html#fetch_argument_or_change/2) # fetch\_argument\_or\_change(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4215) ``` @spec fetch_argument_or_change(t(), atom()) :: {:ok, any()} | :error ``` Gets the value of an argument provided to the changeset, falling back to [`Ash.Changeset.fetch_change/2`](Ash.Changeset.html#fetch_change/2) if nothing was provided. [](Ash.Changeset.html#fetch_change/2) # fetch\_change(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4209) ``` @spec fetch_change(t(), atom()) :: {:ok, any()} | :error ``` Gets the new value for an attribute, or `:error` if it is not being changed. [](Ash.Changeset.html#filter/2) # filter(changeset, expr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5911) ``` @spec filter(t(), Ash.Expr.t()) :: t() ``` Adds a filter for a record being updated or destroyed. Used by optimistic locking. See [`Ash.Resource.Change.Builtins.optimistic_lock/1`](Ash.Resource.Change.Builtins.html#optimistic_lock/1) for more. [](Ash.Changeset.html#for_action/4) # for\_action(initial, action, params \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1264) Constructs a changeset for a given action, and validates it. Calls [`for_create/4`](Ash.Changeset.html#for_create/4), [`for_update/4`](Ash.Changeset.html#for_update/4) or [`for_destroy/4`](Ash.Changeset.html#for_destroy/4) based on the type of action passed in. See those functions for more explanation. [](Ash.Changeset.html#for_create/4) # for\_create(initial, action, params \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1389) Constructs a changeset for a given create action, and validates it. Anything that is modified prior to [`for_create/4`](Ash.Changeset.html#for_create/4) is validated against the rules of the action, while *anything after it is not*. This runs any `change`s contained on your action. To have your logic execute *only* during the action, you can use [`after_action/2`](Ash.Changeset.html#after_action/2) or [`before_action/2`](Ash.Changeset.html#before_action/2). Multitenancy is *not* validated until an action is called. This allows you to avoid specifying a tenant until just before calling the domain action. ### [](Ash.Changeset.html#for_create/4-params)Params `params` may be attributes, relationships, or arguments. You can safely pass user/form input directly into this function. Only public attributes and relationships are supported. If you want to change private attributes as well, see the Customization section below. `params` are stored directly as given in the `params` field of the changeset, which is used ### [](Ash.Changeset.html#for_create/4-opts)Opts - `:require?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `false`, values are only required when the action is run (instead of immediately). The default value is `false`. - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - set the actor, which can be used in any [`Ash.Resource.Change`](Ash.Resource.Change.html)s configured on the action. (in the `context` argument) - `:authorize?` ([`term/0`](../elixir/typespecs.html#built-in-types)) - set authorize?, which can be used in any [`Ash.Resource.Change`](Ash.Resource.Change.html)s configured on the action. (in the `context` argument) - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer to use. Will be carried over to the action. For more information see [`Ash.Tracer`](Ash.Tracer.html). - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - set the tenant on the changeset - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:private_arguments` ([`map/0`](../elixir/typespecs.html#basic-types)) - Private argument values to set before validations and changes. The default value is `%{}`. - `:return_skipped_upsert?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, and a record was *not* upserted because its filter prevented the upsert, the original record (which was *not* upserted) will be returned. The default value is `false`. ### [](Ash.Changeset.html#for_create/4-customization)Customization A changeset can be provided as the first argument, instead of a resource, to allow setting specific attributes ahead of time. For example: ``` MyResource |> Ash.Changeset.new() |> Ash.Changeset.change_attribute(:foo, 1) |> Ash.Changeset.for_create(:create, ...opts) ``` Once a changeset has been validated by [`for_create/4`](Ash.Changeset.html#for_create/4) (or [`for_update/4`](Ash.Changeset.html#for_update/4)), it isn't validated again in the action. New changes added are validated individually, though. This allows you to create a changeset according to a given action, and then add custom changes if necessary. ### [](Ash.Changeset.html#for_create/4-what-does-this-function-do)What does this function do? The following steps are run when calling [`Ash.Changeset.for_create/4`](Ash.Changeset.html#for_create/4). - Cast input params | This is any arguments in addition to any accepted attributes - Set argument defaults - Require any missing arguments - Validate all provided attributes are accepted - Require any accepted attributes that are `allow_nil?` false - Set any default values for attributes - Run action changes &amp; validations - Run validations, or add them in `before_action` hooks if using `Ash.Resource.Dsl.actions.create.validate.before_action?`. Any global validations are skipped if the action has `skip_global_validations?` set to `true`. [](Ash.Changeset.html#for_destroy/4) # for\_destroy(initial, action\_or\_name, params \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1525) Constructs a changeset for a given destroy action, and validates it. ### [](Ash.Changeset.html#for_destroy/4-opts)Opts - `:actor` - set the actor, which can be used in any [`Ash.Resource.Change`](Ash.Resource.Change.html)s configured on the action. (in the `context` argument) - `:tenant` - set the tenant on the changeset - `:private_arguments` - set private arguments on the changeset before validations and changes are run Anything that is modified prior to [`for_destroy/4`](Ash.Changeset.html#for_destroy/4) is validated against the rules of the action, while *anything after it is not*. Once a changeset has been validated by [`for_destroy/4`](Ash.Changeset.html#for_destroy/4), it isn't validated again in the action. New changes added are validated individually, though. This allows you to create a changeset according to a given action, and then add custom changes if necessary. ### [](Ash.Changeset.html#for_destroy/4-what-does-this-function-do)What does this function do? The following steps are run when calling [`Ash.Changeset.for_destroy/4`](Ash.Changeset.html#for_destroy/4). - Cast input params | This is any arguments in addition to any accepted attributes - Set argument defaults - Require any missing arguments - Validate all provided attributes are accepted - Require any accepted attributes that are `allow_nil?` false - Set any default values for attributes - Run action changes &amp; validations - Run validations, or add them in `before_action` hooks if using `Ash.Resource.Dsl.actions.destroy.validate.before_action?`. Any global validations are skipped if the action has `skip_global_validations?` set to `true`. [](Ash.Changeset.html#for_update/4) # for\_update(initial, action, params \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1475) Constructs a changeset for a given update action, and validates it. Anything that is modified prior to [`for_update/4`](Ash.Changeset.html#for_update/4) is validated against the rules of the action, while *anything after it is not*. ### [](Ash.Changeset.html#for_update/4-what-does-this-function-do)What does this function do? The following steps are run when calling [`Ash.Changeset.for_update/4`](Ash.Changeset.html#for_update/4). - Cast input params | This is any arguments in addition to any accepted attributes - Set argument defaults - Require any missing arguments - Validate all provided attributes are accepted - Require any accepted attributes that are `allow_nil?` false - Set any default values for attributes - Run action changes &amp; validations - Run validations, or add them in `before_action` hooks if using `Ash.Resource.Dsl.actions.update.validate.before_action?`. Any global validations are skipped if the action has `skip_global_validations?` set to `true`. [](Ash.Changeset.html#force_change_attribute/3) # force\_change\_attribute(changeset, attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5508) ``` @spec force_change_attribute(t(), atom(), any()) :: t() ``` Changes an attribute even if it isn't writable [](Ash.Changeset.html#force_change_attributes/2) # force\_change\_attributes(changeset, changes) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5500) ``` @spec force_change_attributes(t(), map() | Keyword.t()) :: t() ``` Calls [`force_change_attribute/3`](Ash.Changeset.html#force_change_attribute/3) for each key/value pair provided. [](Ash.Changeset.html#force_change_new_attribute/3) # force\_change\_new\_attribute(changeset, attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5330) ``` @spec force_change_new_attribute(t(), atom(), term()) :: t() ``` Force change an attribute if it is not currently being changed. See [`change_new_attribute/3`](Ash.Changeset.html#change_new_attribute/3) for more. [](Ash.Changeset.html#force_change_new_attribute_lazy/3) # force\_change\_new\_attribute\_lazy(changeset, attribute, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5344) ``` @spec force_change_new_attribute_lazy(t(), atom(), (-> any())) :: t() ``` Force change an attribute if it is not currently being changed, by calling the provided function. See [`change_new_attribute_lazy/3`](Ash.Changeset.html#change_new_attribute_lazy/3) for more. [](Ash.Changeset.html#force_delete_argument/2) # force\_delete\_argument(changeset, argument\_or\_arguments) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5296) Remove an argument from the changeset, not warning if the changeset has already been validated. [](Ash.Changeset.html#force_set_argument/3) # force\_set\_argument(changeset, argument, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5224) Add an argument to the changeset, which will be provided to the action. Does not show a warning when used in before/after action hooks. [](Ash.Changeset.html#force_set_arguments/2) # force\_set\_arguments(changeset, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5318) Merge a map of arguments to the arguments list. Does not show a warning when used in before/after action hooks. [](Ash.Changeset.html#fully_atomic_changeset/4) # fully\_atomic\_changeset(resource, action, params, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L620) ``` @spec fully_atomic_changeset( resource :: Ash.Resource.t(), action :: atom() | Ash.Resource.Actions.action(), params :: map(), opts :: Keyword.t() ) :: t() | {:not_atomic, String.t()} ``` [](Ash.Changeset.html#get_argument/2) # get\_argument(changeset, argument) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4135) ``` @spec get_argument(t(), atom()) :: term() ``` Gets the value of an argument provided to the changeset. [](Ash.Changeset.html#get_argument_or_attribute/2) # get\_argument\_or\_attribute(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4200) ``` @spec get_argument_or_attribute(t(), atom()) :: term() ``` Gets the value of an argument provided to the changeset, falling back to [`Ash.Changeset.get_attribute/2`](Ash.Changeset.html#get_attribute/2) if nothing was provided. [](Ash.Changeset.html#get_attribute/2) # get\_attribute(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4188) ``` @spec get_attribute(t(), atom()) :: term() ``` Gets the changing value or the original value of an attribute. [](Ash.Changeset.html#get_data/2) # get\_data(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4224) ``` @spec get_data(t(), atom()) :: term() ``` Gets the original value for an attribute [](Ash.Changeset.html#handle_errors/2) # handle\_errors(changeset, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5897) ``` @spec handle_errors( t(), (t(), error :: term() -> :ignore | t() | (error :: term()) | {error :: term(), t()}) | {module(), atom(), [term()]} ) :: t() ``` Sets a custom error handler on the changeset. The error handler should be a two argument function or an mfa, in which case the first two arguments will be set to the changeset and the error, w/ the supplied arguments following those. Any errors generated are passed to `handle_errors`, which can return any of the following: - `:ignore` - the error is discarded, and the changeset is not marked as invalid - `changeset` - a new (or the same) changeset. The error is not added (you'll want to add an error yourself), but the changeset *is* marked as invalid. - `{changeset, error}` - a new (or the same) error and changeset. The error is added to the changeset, and the changeset is marked as invalid. - `anything_else` - is treated as a new, transformed version of the error. The result is added as an error to the changeset, and the changeset is marked as invalid. [](Ash.Changeset.html#handle_params/4) # handle\_params(changeset, action, params, handle\_params\_opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L2085) [](Ash.Changeset.html#is_valid/1) # is\_valid(changeset) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L378) ``` @spec is_valid(t()) :: Macro.output() ``` A guard which checks if the Changeset is valid. [](Ash.Changeset.html#load/2) # load(changeset, load) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L509) ``` @spec load(t(), term()) :: t() ``` Calls the provided load statement on the result of the action at the very end of the action. [](Ash.Changeset.html#loading?/2) # loading?(changeset, path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L590) Returns true if the field/relationship or path to field/relationship is being loaded. It accepts an atom or a list of atoms, which is treated for as a "path", i.e: ``` Resource |> Ash.Changeset.load(friends: [enemies: [:score]]) |> Ash.Changeset.loading?([:friends, :enemies, :score]) iex> true Resource |> Ash.Changeset.load(friends: [enemies: [:score]]) |> Ash.Changeset.loading?([:friends, :score]) iex> false Resource |> Ash.Changeset.load(friends: [enemies: [:score]]) |> Ash.Changeset.loading?(:friends) iex> true ``` [](Ash.Changeset.html#manage_relationship/4) # manage\_relationship(changeset, relationship, input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4678) Manages the related records by creating, updating, or destroying them as necessary. Keep in mind that the default values for all `on_*` are `:ignore`, meaning nothing will happen unless you provide instructions. The input provided to `manage_relationship` should be a map, in the case of to\_one relationships, or a list of maps in the case of to\_many relationships. The following steps are followed for each input provided: - The input is checked against the currently related records to find any matches. The primary key and unique identities are used to find matches. - For any input that had a match in the current relationship, the `:on_match` behavior is triggered - For any input that does not have a match: - if there is `on_lookup` behavior: - we try to find the record in the data layer. - if the record is found, the on\_lookup behavior is triggered - if the record is not found, the `on_no_match` behavior is triggered - if there is no `on_lookup` behavior: - the `on_no_match` behavior is triggered - finally, for any records present in the *current relationship* that had no match *in the input*, the `on_missing` behavior is triggered ## [](Ash.Changeset.html#manage_relationship/4-options)Options - `:type` - If the `type` is specified, the default values of each option is modified to match that `type` of operation. This allows for specifying certain operations much more succinctly. The defaults that are modified are listed below: - `:append_and_remove` ``` [ on_lookup: :relate, on_no_match: :error, on_match: :ignore, on_missing: :unrelate ] ``` - `:append` ``` [ on_lookup: :relate, on_no_match: :error, on_match: :ignore, on_missing: :ignore ] ``` - `:remove` ``` [ on_no_match: :error, on_match: :unrelate, on_missing: :ignore ] ``` - `:direct_control` ``` [ on_lookup: :ignore, on_no_match: :create, on_match: :update, on_missing: :destroy ] ``` - `:create` ``` [ on_no_match: :create, on_match: :ignore ] ``` Valid values are :append\_and\_remove, :append, :remove, :direct\_control, :create - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Authorize reads and changes to the destination records, if the primary change is being authorized as well. The default value is `true`. - `:eager_validate_with` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Validates that any referenced entities exist *before* the action is being performed, using the provided domain for the read. The default value is `false`. - `:on_no_match` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Instructions for handling records where no matching record existed in the relationship. - `:ignore` (default) - those inputs are ignored - `:match` - For `has_one` and `belongs_to` only, any input is treated as a match for an existing value. For `has_many` and `many_to_many`, this is the same as `:ignore`. - `:create` - the records are created using the destination's primary create action - `{:create, :action_name}` - the records are created using the specified action on the destination resource - `{:create, :action_name, :join_table_action_name, [:list, :of, :join_table, :params]}` - Same as `{:create, :action_name}` but takes the list of params specified out and applies them when creating the join record, with the provided join\_table\_action\_name. - `:error` - an error is returned indicating that a record would have been created - If `on_lookup` is set, and the data contained a primary key or identity, then the error is a `NotFound` error - Otherwise, an `InvalidRelationship` error is returned The default value is `:ignore`. - `:value_is_key` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Configures what key to use when a single value is provided. This is useful when you use things like a list of strings i.e `friend_emails` to manage the relationship, instead of a list of maps. By default, we assume it is the primary key of the destination resource, unless it is a composite primary key. - `:order_is_key` ([`atom/0`](../elixir/typespecs.html#basic-types)) - If set, the order that each input appears in the list will be added to the input as this key. This is useful when you want to accept an ordered list of related records and write that order to the entity. This should only currently be used with `type: :direct_control` or `type: :create` when there are no currently existing related records (like when creating the source record). If you have an identity on the field and relationship id on the destination, and you are using AshPostgres, you will want to use the `deferrable` option to ensure that conflicting orders are temporarily allowed within a single transaction. - `:identity_priority` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - The list, in priority order, of identities to use when looking up records for `on_lookup`, and matching records with `on_match`. Use `:_primary_key` to prioritize checking a match with the primary key. All identities, along with `:_primary_key` are checked regardless, this only allows ensuring that some are checked first. Defaults to the list provided by `use_identities`, so you typically won't need this option. - `:use_identities` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A list of identities that may be used to look up and compare records. Use `:_primary_key` to include the primary key. By default, only `[:_primary_key]` is used. - `:on_lookup` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Before creating a record (because no match was found in the relationship), the record can be looked up and related. - `:ignore` (default) - Does not look for existing entries (matches in the current relationship are still considered updates) - `:relate` - Same as calling `{:relate, primary_action_name}` - `{:relate, :action_name}` - the records are looked up by primary key/the first identity that is found (using the primary read action), and related. The action should be: - `many_to_many` - a create action on the join resource - `has_many` - an update action on the destination resource - `has_one` - an update action on the destination resource - `belongs_to` - an update action on the source resource - `{:relate, :action_name, :read_action_name}` - Same as the above, but customizes the read action called to search for matches. - `:relate_and_update` - Same as `:relate`, but the remaining parameters from the lookup are passed into the action that is used to change the relationship key - `{:relate_and_update, :action_name}` - Same as the above, but customizes the action used. The action should be: - `many_to_many` - a create action on the join resource - `has_many` - an update action on the destination resource - `has_one` - an update action on the destination resource - `belongs_to` - an update action on the source resource - `{:relate_and_update, :action_name, :read_action_name}` - Same as the above, but customizes the read action called to search for matches. - `{:relate_and_update, :action_name, :read_action_name, [:list, :of, :join_table, :params]}` - Same as the above, but uses the provided list of parameters when creating the join row (only relevant for many to many relationships). Use `:*` to *only* update the join record, and pass all parameters to its action The default value is `:ignore`. - `:on_match` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Instructions for handling records where a matching record existed in the relationship already. - `:ignore` (default) - those inputs are ignored - `:update` - the record is updated using the destination's primary update action - `{:update, :action_name}` - the record is updated using the specified action on the destination resource - `{:update, :action_name, :join_table_action_name, [:list, :of, :params]}` - Same as `{:update, :action_name}` but takes the list of params specified out and applies them as an update to the join record (only valid for many to many) - `:update_join` - update only the join record (only valid for many to many) - `{:update_join, :join_table_action_name}` - use the specified update action on a join resource - `{:update_join, :join_table_action_name, [:list, :of, :params]}` - pass specified params from input into a join resource update action - `{:destroy, :action_name}` - the record is destroyed using the specified action on the destination resource. The action should be: - `many_to_many` - a destroy action on the join record - `has_many` - a destroy action on the destination resource - `has_one` - a destroy action on the destination resource - `belongs_to` - a destroy action on the destination resource - `:error` - an error is returned indicating that a record would have been updated - `:no_match` - follows the `on_no_match` instructions with these records - `:missing` - follows the `on_missing` instructions with these records - `:unrelate` - the related item is not destroyed, but the data is "unrelated", making this behave like `remove_from_relationship/3`. The action should be: - `many_to_many` - the join resource row is destroyed - `has_many` - the `destination_attribute` (on the related record) is set to `nil` - `has_one` - the `destination_attribute` (on the related record) is set to `nil` - `belongs_to` - the `source_attribute` (on this record) is set to `nil` - `{:unrelate, :action_name}` - the record is unrelated using the provided update action. The action should be: - `many_to_many` - a destroy action on the join resource - `has_many` - an update action on the destination resource - `has_one` - an update action on the destination resource - `belongs_to` - an update action on the source resource The default value is `:ignore`. - `:on_missing` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Instructions for handling records that existed in the current relationship but not in the input. - `:ignore` (default) - those inputs are ignored - `:destroy` - the record is destroyed using the destination's primary destroy action - `{:destroy, :action_name}` - the record is destroyed using the specified action on the destination resource - `{:destroy, :action_name, :join_resource_action_name}` - the record is destroyed using the specified action on the destination resource, but first the join resource is destroyed with its specified action - `:error` - an error is returned indicating that a record would have been updated - `:unrelate` - the related item is not destroyed, but the data is "unrelated", making this behave like `remove_from_relationship/3`. The action should be: - `many_to_many` - the join resource row is destroyed - `has_many` - the `destination_attribute` (on the related record) is set to `nil` - `has_one` - the `destination_attribute` (on the related record) is set to `nil` - `belongs_to` - the `source_attribute` (on this record) is set to `nil` - `{:unrelate, :action_name}` - the record is unrelated using the provided update action. The action should be: - `many_to_many` - a destroy action on the join resource - `has_many` - an update action on the destination resource - `has_one` - an update action on the destination resource - `belongs_to` - an update action on the source resource The default value is `:ignore`. - `:error_path` ([`term/0`](../elixir/typespecs.html#built-in-types)) - By default, errors added to the changeset will use the path `[:relationship_name]`, or `[:relationship_name, <index>]`. If you want to modify this path, you can specify `error_path`, e.g if had a `change` on an action that takes an argument and uses that argument data to call `manage_relationship`, you may want any generated errors to appear under the name of that argument, so you could specify `error_path: :argument_name` when calling `manage_relationship`. - `:join_keys` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - For many to many relationships specifies the parameters to pick from the input and pass into a join resource action. Applicable in cases like `on_no_match: :create`, `on_match: :update` and `on_lookup: :relate`. Can be overwritten by a full form instruction tuple which contains join parameters at the end. - `:meta` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Freeform data that will be retained along with the options, which can be used to track/manage the changes that are added to the `relationships` key. Use the `meta[:order]` option to specify the order in which multiple calls to `manage_relationship` should be executed. - `:ignore?` ([`term/0`](../elixir/typespecs.html#built-in-types)) - This tells Ash to ignore the provided inputs when actually running the action. This can be useful for building up a set of instructions that you intend to handle manually. The default value is `false`. Each call to this function adds new records that will be handled according to their options. For example, if you tracked "tags to add" and "tags to remove" in separate fields, you could input them like so: ``` changeset |> Ash.Changeset.manage_relationship( :tags, [%{name: "backend"}], on_lookup: :relate, #relate that tag if it exists in the database on_no_match: :error # error if a tag with that name doesn't exist ) |> Ash.Changeset.manage_relationship( :tags, [%{name: "frontend"}], on_no_match: :error, # error if a tag with that name doesn't exist in the relationship on_match: :unrelate # if a tag with that name is related, unrelate it ) ``` When calling this multiple times with the `on_missing` option set, the list of records that are considered missing are checked after each set of inputs is processed. For example, if you manage the relationship once with `on_missing: :unrelate`, the records missing from your input will be removed, and *then* your next call to `manage_relationship` will be resolved (with those records unrelated). For this reason, it is suggested that you don't call this function multiple times with an `on_missing` instruction, as you may be surprised by the result. If you want the input to update existing entities, you need to ensure that the primary key (or unique identity) is provided as part of the input. See the example below: ``` changeset |> Ash.Changeset.manage_relationship( :comments, [%{rating: 10, contents: "foo"}], on_no_match: {:create, :create_action}, on_missing: :ignore ) |> Ash.Changeset.manage_relationship( :comments, [%{id: 10, rating: 10, contents: "foo"}], on_match: {:update, :update_action}, on_no_match: {:create, :create_action}) ``` This is a simple way to manage a relationship. If you need custom behavior, you can customize the action that is called, which allows you to add arguments/changes. However, at some point you may want to forego this function and make the changes yourself. For example: ``` input = [%{id: 10, rating: 10, contents: "foo"}] changeset |> Ash.Changeset.after_action(fn _changeset, result -> # An example of updating comments based on a result of other changes for comment <- input do comment = Ash.get(Comment, comment.id) comment |> Map.update(:rating, 0, &(&1 * result.rating_weight)) |> Ash.update!() end {:ok, result} end) ``` ## [](Ash.Changeset.html#manage_relationship/4-using-records-as-input)Using records as input Records can be supplied as the input values. If you do: - if it would be looked up due to `on_lookup`, the record is used as-is - if it would be created due to `on_no_match`, the record is used as-is - Instead of specifying `join_keys`, those keys must go in `__metadata__.join_keys`. If `join_keys` is specified in the options, it is ignored. For example: ``` post1 = changeset |> Ash.create!() |> Ash.Resource.put_metadata(:join_keys, %{type: "a"}) post1 = changeset2 |> Ash.create!() |> Ash.Resource.put_metadata(:join_keys, %{type: "b"}) author = Ash.create!(author_changeset) Ash.Changeset.manage_relationship( author, :posts, [post1, post2], on_lookup: :relate ) ``` [](Ash.Changeset.html#manage_relationship_opts/1) # manage\_relationship\_opts(atom) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4271) ``` @spec manage_relationship_opts(manage_relationship_type()) :: Keyword.t() ``` [](Ash.Changeset.html#new/1) # new(record\_or\_resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L397) ``` @spec new(Ash.Resource.t() | Ash.Resource.record()) :: t() ``` Returns a new changeset over a resource. *Warning*: You almost always want to use `for_action` or `for_create`, etc. over this function if possible. You can use this to start a changeset and make changes prior to calling `for_action`. This is not typically necessary, but can be useful as an escape hatch. For example: ``` Resource |> Ash.Changeset.new() |> Ash.Changeset.change_attribute(:name, "foobar") |> Ash.Changeset.for_action(...) ``` [](Ash.Changeset.html#prepare_changeset_for_action/3) # prepare\_changeset\_for\_action(changeset, action, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L2066) [](Ash.Changeset.html#present?/2) # present?(changeset, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L2010) Checks if an argument is not nil or an attribute is not nil, either in the original data, or that it is not being changed to a `nil` value if it is changing. This also accounts for the `accessing_from` context that is set when using `manage_relationship`, so it is aware that a particular value *will* be set by `manage_relationship` even if it isn't currently being set. [](Ash.Changeset.html#put_context/3) # put\_context(changeset, key, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4234) ``` @spec put_context(t(), atom(), term()) :: t() ``` Puts a key/value in the changeset context that can be used later. Do not use the `private` key in your custom context, as that is reserved for internal use. [](Ash.Changeset.html#run_atomic_change/3) # run\_atomic\_change(changeset, map, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L943) [](Ash.Changeset.html#run_before_transaction_hooks/1) # run\_before\_transaction\_hooks(changeset) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L3805) [](Ash.Changeset.html#select/3) # select(changeset, fields, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L448) Ensure that only the specified attributes are present in the results. The first call to [`select/2`](Ash.Changeset.html#select/2) will replace the default behavior of selecting all attributes. Subsequent calls to [`select/2`](Ash.Changeset.html#select/2) will combine the provided fields unless the `replace?` option is provided with a value of `true`. If a field has been deselected, selecting it again will override that (because a single list of fields is tracked for selection) Primary key attributes always selected and cannot be deselected. When attempting to load a relationship (or manage it with [`Ash.Changeset.manage_relationship/3`](Ash.Changeset.html#manage_relationship/3)), if the source field is not selected on the query/provided data an error will be produced. If loading a relationship with a query, an error is produced if the query does not select the destination field of the relationship. Datalayers currently are not notified of the `select` for a changeset(unlike queries), and creates/updates select all fields when they are performed. A select provided on a changeset sets the unselected fields to `nil` before returning the result. Use [`ensure_selected/2`](Ash.Changeset.html#ensure_selected/2) if you wish to make sure a field has been selected, without deselecting any other fields. [](Ash.Changeset.html#selecting?/2) # selecting?(changeset, field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L560) [](Ash.Changeset.html#set_argument/3) # set\_argument(changeset, argument, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5167) Add an argument to the changeset, which will be provided to the action. [](Ash.Changeset.html#set_arguments/2) # set\_arguments(changeset, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5307) Merge a map of arguments to the arguments list. [](Ash.Changeset.html#set_context/2) # set\_context(changeset, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4254) ``` @spec set_context(t(), map() | nil) :: t() ``` Deep merges the provided map into the changeset context that can be used later. Do not use the `private` key in your custom context, as that is reserved for internal use. [](Ash.Changeset.html#set_on_upsert/2) # set\_on\_upsert(changeset, upsert\_keys) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1842) ``` @spec set_on_upsert(t(), [atom()]) :: Keyword.t() ``` [](Ash.Changeset.html#set_private_argument/3) # set\_private\_argument(changeset, argument, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5176) ``` @spec set_private_argument(t(), atom(), term()) :: t() ``` Add a private argument to the changeset, which will be provided to the action. [](Ash.Changeset.html#set_result/2) # set\_result(changeset, result) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L1814) ``` @spec set_result(t(), term()) :: t() ``` Set the result of the action. This will prevent running the underlying datalayer behavior [](Ash.Changeset.html#set_tenant/2) # set\_tenant(changeset, tenant) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4239) ``` @spec set_tenant(t(), Ash.ToTenant.t()) :: t() ``` [](Ash.Changeset.html#timeout/3) # timeout(changeset, timeout, default \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L4244) ``` @spec timeout(t(), nil | pos_integer(), nil | pos_integer()) :: t() ``` [](Ash.Changeset.html#update_change/3) # update\_change(changeset, attribute, fun) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L5154) ``` @spec update_change(t(), atom(), (any() -> any())) :: t() ``` Updates an existing attribute change by applying a function to it. This is useful for applying some kind of normalization to the attribute. ``` Ash.Changeset.update_change(changeset, :serial, &String.downcase/1) ``` The update function gets called with the value already cast to the correct type. ``` changeset |> Ash.Changeset.change_attribute(:integer_attribute, "3") |> Ash.Changeset.update_change(:integer_attribute, fn x -> x + 1 end) ``` ## [](Ash.Changeset.html#update_change/3-invalid-value-handling)Invalid value handling If `update_change` is called with a changeset that has not been validated yet, the update function must handle potentially invalid and `nil` values. To only deal with valid values, you can call `update_change` in a `before_action` hook. [](Ash.Changeset.html#with_hooks/3) # with\_hooks(changeset, func, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L3500) ``` @spec with_hooks( t(), (t() -> {:ok, term(), %{notifications: [Ash.Notifier.Notification.t()]}} | {:error, term()}), Keyword.t() ) :: {:ok, term(), t(), %{notifications: [Ash.Notifier.Notification.t()]}} | {:error, term()} ``` Wraps a function in the before/after action hooks of a changeset. The function takes a changeset and if it returns `{:ok, result}`, the result will be passed through the after action hooks. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Changeset.ManagedRelationshipHelpers (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L1 "View Source") Tools for introspecting managed relationships. Extensions can use this to look at an argument that will be passed to a `manage_relationship` change and determine what their behavior should be. For example, AshAdmin uses these to find out what kind of nested form it should offer for each argument that manages a relationship. # [](Ash.Changeset.ManagedRelationshipHelpers.html#summary)Summary ## [Functions](Ash.Changeset.ManagedRelationshipHelpers.html#functions) [could\_create?(opts)](Ash.Changeset.ManagedRelationshipHelpers.html#could_create?/1) [could\_handle\_missing?(opts)](Ash.Changeset.ManagedRelationshipHelpers.html#could_handle_missing?/1) [could\_lookup?(opts)](Ash.Changeset.ManagedRelationshipHelpers.html#could_lookup?/1) [could\_update?(opts)](Ash.Changeset.ManagedRelationshipHelpers.html#could_update?/1) [must\_load?(opts, must\_load\_opts \\\\ \[\])](Ash.Changeset.ManagedRelationshipHelpers.html#must_load?/2) [on\_lookup\_read\_action(opts, relationship)](Ash.Changeset.ManagedRelationshipHelpers.html#on_lookup_read_action/2) [on\_lookup\_update\_action(opts, relationship)](Ash.Changeset.ManagedRelationshipHelpers.html#on_lookup_update_action/2) [on\_match\_destination\_actions(opts, relationship)](Ash.Changeset.ManagedRelationshipHelpers.html#on_match_destination_actions/2) [on\_missing\_destination\_actions(opts, relationship)](Ash.Changeset.ManagedRelationshipHelpers.html#on_missing_destination_actions/2) [on\_no\_match\_destination\_actions(opts, relationship)](Ash.Changeset.ManagedRelationshipHelpers.html#on_no_match_destination_actions/2) [sanitize\_opts(relationship, opts)](Ash.Changeset.ManagedRelationshipHelpers.html#sanitize_opts/2) # [](Ash.Changeset.ManagedRelationshipHelpers.html#functions)Functions [](Ash.Changeset.ManagedRelationshipHelpers.html#could_create?/1) # could\_create?(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L284) [](Ash.Changeset.ManagedRelationshipHelpers.html#could_handle_missing?/1) # could\_handle\_missing?(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L276) [](Ash.Changeset.ManagedRelationshipHelpers.html#could_lookup?/1) # could\_lookup?(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L280) [](Ash.Changeset.ManagedRelationshipHelpers.html#could_update?/1) # could\_update?(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L288) [](Ash.Changeset.ManagedRelationshipHelpers.html#must_load?/2) # must\_load?(opts, must\_load\_opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L292) [](Ash.Changeset.ManagedRelationshipHelpers.html#on_lookup_read_action/2) # on\_lookup\_read\_action(opts, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L248) [](Ash.Changeset.ManagedRelationshipHelpers.html#on_lookup_update_action/2) # on\_lookup\_update\_action(opts, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L229) [](Ash.Changeset.ManagedRelationshipHelpers.html#on_match_destination_actions/2) # on\_match\_destination\_actions(opts, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L151) [](Ash.Changeset.ManagedRelationshipHelpers.html#on_missing_destination_actions/2) # on\_missing\_destination\_actions(opts, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L205) [](Ash.Changeset.ManagedRelationshipHelpers.html#on_no_match_destination_actions/2) # on\_no\_match\_destination\_actions(opts, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L187) [](Ash.Changeset.ManagedRelationshipHelpers.html#sanitize_opts/2) # sanitize\_opts(relationship, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/managed_relationship_helpers.ex#L11) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Changeset.OriginalDataNotAvailable (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L311 "View Source") A value placed in changeset.data to indicate that the original data is not available # [](Ash.Changeset.OriginalDataNotAvailable.html#summary)Summary ## [Types](Ash.Changeset.OriginalDataNotAvailable.html#types) [t()](Ash.Changeset.OriginalDataNotAvailable.html#t:t/0) # [](Ash.Changeset.OriginalDataNotAvailable.html#types)Types [](Ash.Changeset.OriginalDataNotAvailable.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/changeset/changeset.ex#L314) ``` @type t() :: %Ash.Changeset.OriginalDataNotAvailable{reason: :atomic_query_update} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.CiString (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L1 "View Source") Represents a case insensitive string While some data layers are aware of case insensitive string types, in order for values of this type to be used in other parts of Ash Framework, it has to be embedded in a module this allows us to implement the [`Comparable`](Comparable.html) protocol for it. For the type implementation, see [`Ash.Type.CiString`](Ash.Type.CiString.html) # [](Ash.CiString.html#summary)Summary ## [Types](Ash.CiString.html#types) [casing()](Ash.CiString.html#t:casing/0) [string\_type()](Ash.CiString.html#t:string_type/0) [t()](Ash.CiString.html#t:t/0) ## [Functions](Ash.CiString.html#functions) [compare(left, right)](Ash.CiString.html#compare/2) Compares an Elixir String or Ash.CiString. It will return `:eq` if equal, `:lt`, if the string is ordered alphabetically before the second string, and `:gt` if after. [new(value, casing \\\\ nil)](Ash.CiString.html#new/2) Returns a Ash.CiString from a String, or `nil` if the value is `nil`. [sigil\_i(value, mods)](Ash.CiString.html#sigil_i/2) Creates a case insensitive string [to\_comparable\_string(value)](Ash.CiString.html#to_comparable_string/1) Returns the downcased value, only downcasing if it hasn't already been done [value(ci\_string)](Ash.CiString.html#value/1) Converts a [`Ash.CiString`](Ash.CiString.html) into a normal Elixir String. # [](Ash.CiString.html#types)Types [](Ash.CiString.html#t:casing/0) # casing() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L14) ``` @type casing() :: nil | :lower | :upper ``` [](Ash.CiString.html#t:string_type/0) # string\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L21) ``` @type string_type() :: t() | String.t() ``` [](Ash.CiString.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L16) ``` @type t() :: %Ash.CiString{case: casing(), casted?: boolean(), string: String.t()} ``` # [](Ash.CiString.html#functions)Functions [](Ash.CiString.html#compare/2) # compare(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L106) ``` @spec compare(string_type(), string_type()) :: :gt | :lt | :eq ``` Compares an Elixir String or Ash.CiString. It will return `:eq` if equal, `:lt`, if the string is ordered alphabetically before the second string, and `:gt` if after. [](Ash.CiString.html#new/2) # new(value, casing \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L64) ``` @spec new(string_type() | nil, casing()) :: t() | nil ``` Returns a Ash.CiString from a String, or `nil` if the value is `nil`. [](Ash.CiString.html#sigil_i/2) # sigil\_i(value, mods) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L25) ``` @spec sigil_i( string_type() | nil, charlist() ) :: t() ``` Creates a case insensitive string [](Ash.CiString.html#to_comparable_string/1) # to\_comparable\_string(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L116) ``` @spec to_comparable_string(string_type() | nil) :: String.t() | nil ``` Returns the downcased value, only downcasing if it hasn't already been done [](Ash.CiString.html#value/1) # value(ci\_string) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L89) ``` @spec value(t()) :: String.t() ``` Converts a [`Ash.CiString`](Ash.CiString.html) into a normal Elixir String. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.CodeInterface (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L1 "View Source") Used to define the functions of a code interface for a resource. # [](Ash.CodeInterface.html#summary)Summary ## [Functions](Ash.CodeInterface.html#functions) [define\_interface(domain, resource, definitions \\\\ nil)](Ash.CodeInterface.html#define_interface/3) Defines the code interface for a given resource + domain combination in the current module. For example [describe\_action(resource, action, args)](Ash.CodeInterface.html#describe_action/3) [describe\_calculation(resource, calculation, args)](Ash.CodeInterface.html#describe_calculation/3) [merge\_default\_opts(opts, default\_opts)](Ash.CodeInterface.html#merge_default_opts/2) Selectively merges default opts into client-provided opts. For most keys, the value in opts will be used instead of the default if provided. However, certain options have special behavior [params\_and\_opts(params, opts)](Ash.CodeInterface.html#params_and_opts/2) A common pattern is for a function to have both optional parameters and optional options. This usually comes in the form of two defaults [params\_and\_opts(params\_or\_opts, maybe\_opts, post\_process\_opts\_fn)](Ash.CodeInterface.html#params_and_opts/3) See [`params_and_opts/2`](Ash.CodeInterface.html#params_and_opts/2). [trim\_double\_newlines(str)](Ash.CodeInterface.html#trim_double_newlines/1) [unwrap\_calc\_interface\_args(keys, resource, arguments, function\_head? \\\\ false)](Ash.CodeInterface.html#unwrap_calc_interface_args/4) [without\_optional(keys)](Ash.CodeInterface.html#without_optional/1) # [](Ash.CodeInterface.html#functions)Functions [](Ash.CodeInterface.html#define_interface/3) # define\_interface(domain, resource, definitions \\\\ nil) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L345) Defines the code interface for a given resource + domain combination in the current module. For example: ``` defmodule MyApp.Accounting do require Ash.CodeInterface Ash.CodeInterface.define_interface(MyApp.Accounting, MyApp.Accounting.Transaction) Ash.CodeInterface.define_interface(MyApp.Accounting, MyApp.Accounting.Account) Ash.CodeInterface.define_interface(MyApp.Accounting, MyApp.Accounting.Invoice) end ``` [](Ash.CodeInterface.html#describe_action/3) # describe\_action(resource, action, args) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L1607) [](Ash.CodeInterface.html#describe_calculation/3) # describe\_calculation(resource, calculation, args) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L1657) [](Ash.CodeInterface.html#merge_default_opts/2) # merge\_default\_opts(opts, default\_opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L310) ``` @spec merge_default_opts(keyword(), keyword()) :: keyword() ``` Selectively merges default opts into client-provided opts. For most keys, the value in opts will be used instead of the default if provided. However, certain options have special behavior: - `:bulk_options`, `:page` - These options are deep merged, so if the default is a keyword list and the client value is a keyword list, they'll be merged. - `:load` - The default value and the client value will be combined in this case. ## [](Ash.CodeInterface.html#merge_default_opts/2-examples)Examples ``` iex> merge_default_opts([key1: 1], key2: 2) [key2: 2, key1: 1] iex> merge_default_opts([key2: :client], key1: :default, key2: :default) [key2: :client, key1: :default] iex> merge_default_opts([page: false], page: [limit: 100]) [page: false] iex> merge_default_opts([page: [offset: 2]], page: [limit: 100]) [page: [limit: 100, offset: 2]] iex> merge_default_opts([load: [:calc2, :rel4]], load: [:calc1, rel1: [:rel2, :rel3]]) [load: [:calc1, {:rel1, [:rel2, :rel3]}, :calc2, :rel4]] ``` [](Ash.CodeInterface.html#params_and_opts/2) # params\_and\_opts(params, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L240) ``` @spec params_and_opts( params_or_opts :: map() | [map()] | keyword(), keyword() ) :: {params :: map() | [map()], opts :: keyword()} ``` A common pattern is for a function to have both optional parameters and optional options. This usually comes in the form of two defaults: - An empty map for params. - An empty list for options. With those two defaults in mind, this function will decipher, from two inputs, which should be parameters and which should be options. Parameters can take one of two primary forms: 1. A map. 2. A list of maps for bulk operations. Additionally, if options are set explicitly (i.e. at least one option has been set), a keyword list will be converted to a map. ## [](Ash.CodeInterface.html#params_and_opts/2-examples)Examples ``` iex> params_and_opts(%{key: :param}, [key: :opt]) {%{key: :param}, [key: :opt]} iex> params_and_opts([key: :opt], []) {%{}, [key: :opt]} iex> params_and_opts([], []) {[], []} iex> params_and_opts([%{key: :param}], []) {[%{key: :param}], []} iex> params_and_opts([key: :param], [key: :opt]) {%{key: :param}, [key: :opt]} ``` [](Ash.CodeInterface.html#params_and_opts/3) # params\_and\_opts(params\_or\_opts, maybe\_opts, post\_process\_opts\_fn) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L269) ``` @spec params_and_opts( params_or_opts :: map() | [map()] | keyword(), keyword(), (keyword() -> keyword()) ) :: {params :: map() | [map()], opts :: keyword()} ``` See [`params_and_opts/2`](Ash.CodeInterface.html#params_and_opts/2). Adds a post process function that can takes the opts and can further process, validate, or transform them. [](Ash.CodeInterface.html#trim_double_newlines/1) # trim\_double\_newlines(str) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L1731) [](Ash.CodeInterface.html#unwrap_calc_interface_args/4) # unwrap\_calc\_interface\_args(keys, resource, arguments, function\_head? \\\\ false) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L87) [](Ash.CodeInterface.html#without_optional/1) # without\_optional(keys) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/code_interface.ex#L77) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/context.ex#L1 "View Source") Functions for working with the context provided to various callbacks in Ash. # [](Ash.Context.html#summary)Summary ## [Types](Ash.Context.html#types) [context\_keyword\_list()](Ash.Context.html#t:context_keyword_list/0) ## [Functions](Ash.Context.html#functions) [to\_opts(map, opts \\\\ \[\])](Ash.Context.html#to_opts/2) Copies keys from the given context map into a keyword list. Does *not* copy the `:domain` key. # [](Ash.Context.html#types)Types [](Ash.Context.html#t:context_keyword_list/0) # context\_keyword\_list() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/context.ex#L6) ``` @type context_keyword_list() :: [ actor: Ash.Resource.t(), authorize?: boolean(), tracer: Ash.Tracer.t(), tenant: Ash.Resource.t() ] ``` # [](Ash.Context.html#functions)Functions [](Ash.Context.html#to_opts/2) # to\_opts(map, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/context.ex#L24) ``` @spec to_opts(map(), Keyword.t()) :: context_keyword_list() ``` Copies keys from the given context map into a keyword list. Does *not* copy the `:domain` key. Keys copied: - `:actor` - `:authorize?` - `:tracer` - `:tenant` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.CustomExpression behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/custom_expression.ex#L1 "View Source") A module for defining custom functions that can be called in Ash expressions. For example: ``` defmodule MyApp.Expressions.LevenshteinDistance do use Ash.CustomExpression, name: :levenshtein, arguments: [ [:string, :string] ] def expression(AshPostgres.DataLayer, [left, right]) do {:ok, expr(fragment("levenshtein(?, ?)", left, right))} end # It is good practice to always define an expression for `Ash.DataLayer.Simple`, # as that is what Ash will use to run your custom expression in Elixir. # This allows us to completely avoid communicating with the database in some cases. def expression(data_layer, [left, right]) when data_layer in [ Ash.DataLayer.Ets, Ash.DataLayer.Simple ] do {:ok, expr(fragment(&__MODULE__.levenshtein/2, left, right))} end # always define this fallback clause as well def expression(_data_layer, _args), do: :unknown @doc "Computes the levenshtein distance of two strings" def levenshtein(left, right) do # ...... end end ``` ### [](Ash.CustomExpression.html#module-options)Options - `name` - The name of the custom expression. This is the name that will be used in Ash expressions. - `arguments` - A list of lists of types that the custom expression accepts. Each list represents a set of arguments that the custom expression can accept. - `predicate?` - Whether this expression can be exposed as a predicate in filter interfaces. Defaults to `false`. ### [](Ash.CustomExpression.html#module-registering-your-expression)Registering Your Expression Use compile-time configuration to register your custom expressions ``` config :ash, :custom_expressions, [MyApp.Expressions.LevenshteinDistance] ``` # [](Ash.CustomExpression.html#summary)Summary ## [Callbacks](Ash.CustomExpression.html#callbacks) [arguments()](Ash.CustomExpression.html#c:arguments/0) [expression(data\_layer, arguments)](Ash.CustomExpression.html#c:expression/2) [name()](Ash.CustomExpression.html#c:name/0) # [](Ash.CustomExpression.html#callbacks)Callbacks [](Ash.CustomExpression.html#c:arguments/0) # arguments() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/custom_expression.ex#L73) ``` @callback arguments() :: [[Ash.Type.t() | {Ash.Type.t(), Keyword.t()}]] ``` [](Ash.CustomExpression.html#c:expression/2) # expression(data\_layer, arguments) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/custom_expression.ex#L65) ``` @callback expression( data_layer :: Ash.DataLayer.t(), arguments :: [Ash.Expr.t()] ) :: {:ok, Ash.Expr.t()} | :unknown ``` [](Ash.CustomExpression.html#c:name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/custom_expression.ex#L71) ``` @callback name() :: atom() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Ets (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/ets/ets.ex#L1 "View Source") An ETS (Erlang Term Storage) backed Ash Datalayer, for testing and lightweight usage. Remember, this does not have support for transactions! This is not recommended for production use, especially in multi-user applications. It can, however, be great for prototyping. # [](Ash.DataLayer.Ets.html#summary)Summary ## [Functions](Ash.DataLayer.Ets.html#functions) [do\_add\_calculations(records, resource, calculations, domain)](Ash.DataLayer.Ets.html#do_add_calculations/4) [ets(body)](Ash.DataLayer.Ets.html#ets/1) [stop(resource, tenant \\\\ nil)](Ash.DataLayer.Ets.html#stop/2) Stops the storage for a given resource/tenant (deleting all of the data) # [](Ash.DataLayer.Ets.html#functions)Functions [](Ash.DataLayer.Ets.html#do_add_calculations/4) # do\_add\_calculations(records, resource, calculations, domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/ets/ets.ex#L618) [](Ash.DataLayer.Ets.html#ets/1) # ets(body) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/ets/ets.ex#L43) [](Ash.DataLayer.Ets.html#stop/2) # stop(resource, tenant \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/ets/ets.ex#L140) Stops the storage for a given resource/tenant (deleting all of the data) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Ets.Info (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/ets/info.ex#L1 "View Source") Introspection helpers for the Ets data layer # [](Ash.DataLayer.Ets.Info.html#summary)Summary ## [Functions](Ash.DataLayer.Ets.Info.html#functions) [private?(resource)](Ash.DataLayer.Ets.Info.html#private?/1) Whether or not the ets table for the resource should be private [table(resource)](Ash.DataLayer.Ets.Info.html#table/1) The ets table name for a resource # [](Ash.DataLayer.Ets.Info.html#functions)Functions [](Ash.DataLayer.Ets.Info.html#private?/1) # private?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/ets/info.ex#L8) ``` @spec private?(Ash.Resource.t() | Spark.Dsl.t()) :: boolean() ``` Whether or not the ets table for the resource should be private [](Ash.DataLayer.Ets.Info.html#table/1) # table(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/ets/info.ex#L14) ``` @spec table(Ash.Resource.t() | Spark.Dsl.t()) :: boolean() ``` The ets table name for a resource [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L1 "View Source") The behaviour for backing resource actions with persistence layers. # [](Ash.DataLayer.html#summary)Summary ## [Types](Ash.DataLayer.html#types) [bulk\_create\_options()](Ash.DataLayer.html#t:bulk_create_options/0) [bulk\_update\_options()](Ash.DataLayer.html#t:bulk_update_options/0) [data\_layer\_query()](Ash.DataLayer.html#t:data_layer_query/0) [feature()](Ash.DataLayer.html#t:feature/0) [lateral\_join\_link()](Ash.DataLayer.html#t:lateral_join_link/0) [lock\_type()](Ash.DataLayer.html#t:lock_type/0) [t()](Ash.DataLayer.html#t:t/0) [transaction\_reason()](Ash.DataLayer.html#t:transaction_reason/0) ## [Callbacks](Ash.DataLayer.html#callbacks) [add\_aggregate(data\_layer\_query, t, t)](Ash.DataLayer.html#c:add_aggregate/3) [add\_aggregates(data\_layer\_query, list, t)](Ash.DataLayer.html#c:add_aggregates/3) [add\_calculation(data\_layer\_query, t, expression, t)](Ash.DataLayer.html#c:add_calculation/4) [add\_calculations(data\_layer\_query, list, t)](Ash.DataLayer.html#c:add_calculations/3) [bulk\_create(t, t, options)](Ash.DataLayer.html#c:bulk_create/3) [calculate(t, list, context)](Ash.DataLayer.html#c:calculate/3) [can?(arg1, feature)](Ash.DataLayer.html#c:can?/2) [create(t, t)](Ash.DataLayer.html#c:create/2) [destroy(t, t)](Ash.DataLayer.html#c:destroy/2) [destroy\_query(data\_layer\_query, t, t, opts)](Ash.DataLayer.html#c:destroy_query/4) [distinct(data\_layer\_query, list, resource)](Ash.DataLayer.html#c:distinct/3) [distinct\_sort(data\_layer\_query, t, resource)](Ash.DataLayer.html#c:distinct_sort/3) [filter(data\_layer\_query, t, resource)](Ash.DataLayer.html#c:filter/3) [functions(t)](Ash.DataLayer.html#c:functions/1) [in\_transaction?(t)](Ash.DataLayer.html#c:in_transaction?/1) [limit(data\_layer\_query, limit, resource)](Ash.DataLayer.html#c:limit/3) [lock(data\_layer\_query, lock\_type, resource)](Ash.DataLayer.html#c:lock/3) [offset(data\_layer\_query, offset, resource)](Ash.DataLayer.html#c:offset/3) [prefer\_lateral\_join\_for\_many\_to\_many?()](Ash.DataLayer.html#c:prefer_lateral_join_for_many_to_many?/0) [prefer\_transaction?(t)](Ash.DataLayer.html#c:prefer_transaction?/1) [prefer\_transaction\_for\_atomic\_updates?(t)](Ash.DataLayer.html#c:prefer_transaction_for_atomic_updates?/1) [resource\_to\_query(t, t)](Ash.DataLayer.html#c:resource_to_query/2) [return\_query(data\_layer\_query, t)](Ash.DataLayer.html#c:return_query/2) [rollback(t, term)](Ash.DataLayer.html#c:rollback/2) [run\_aggregate\_query(data\_layer\_query, list, t)](Ash.DataLayer.html#c:run_aggregate_query/3) [run\_aggregate\_query\_with\_lateral\_join(data\_layer\_query, list, list, destination\_resource, list)](Ash.DataLayer.html#c:run_aggregate_query_with_lateral_join/5) [run\_query(data\_layer\_query, t)](Ash.DataLayer.html#c:run_query/2) [run\_query\_with\_lateral\_join(data\_layer\_query, list, source\_resource, list)](Ash.DataLayer.html#c:run_query_with_lateral_join/4) [select(data\_layer\_query, select, resource)](Ash.DataLayer.html#c:select/3) [set\_context(t, data\_layer\_query, map)](Ash.DataLayer.html#c:set_context/3) [set\_tenant(t, data\_layer\_query, term)](Ash.DataLayer.html#c:set_tenant/3) [sort(data\_layer\_query, t, resource)](Ash.DataLayer.html#c:sort/3) [source(t)](Ash.DataLayer.html#c:source/1) [transaction(t, function, arg3, reason)](Ash.DataLayer.html#c:transaction/4) [transform\_query(t)](Ash.DataLayer.html#c:transform_query/1) [update(t, t)](Ash.DataLayer.html#c:update/2) [update\_query(data\_layer\_query, t, t, opts)](Ash.DataLayer.html#c:update_query/4) [upsert(t, t, list)](Ash.DataLayer.html#c:upsert/3) [upsert(t, t, list, arg4)](Ash.DataLayer.html#c:upsert/4) ## [Functions](Ash.DataLayer.html#functions) [add\_aggregates(query, aggregates, resource)](Ash.DataLayer.html#add_aggregates/3) [add\_calculations(query, calculations, resource)](Ash.DataLayer.html#add_calculations/3) [bulk\_create(resource, changesets, options)](Ash.DataLayer.html#bulk_create/3) [calculate(resource, exprs, context)](Ash.DataLayer.html#calculate/3) [can?(feature, resource)](Ash.DataLayer.html#can?/2) [create(resource, changeset)](Ash.DataLayer.html#create/2) [data\_layer(resource)](Ash.DataLayer.html#data_layer/1) The data layer of the resource, or nil if it does not have one [data\_layer\_can?(resource, feature)](Ash.DataLayer.html#data_layer_can?/2) Whether or not the data layer supports a specific feature [data\_layer\_functions(resource)](Ash.DataLayer.html#data_layer_functions/1) Custom functions supported by the data layer of the resource [destroy(resource, changeset)](Ash.DataLayer.html#destroy/2) [destroy\_query(query, changeset, opts)](Ash.DataLayer.html#destroy_query/3) [distinct(query, distinct, resource)](Ash.DataLayer.html#distinct/3) [distinct\_sort(query, sort, resource)](Ash.DataLayer.html#distinct_sort/3) [filter(query, filter, resource)](Ash.DataLayer.html#filter/3) [functions(resource)](Ash.DataLayer.html#functions/1) [in\_transaction?(resource)](Ash.DataLayer.html#in_transaction?/1) [limit(query, limit, resource)](Ash.DataLayer.html#limit/3) [lock(query, lock\_type, resource)](Ash.DataLayer.html#lock/3) [offset(query, offset, resource)](Ash.DataLayer.html#offset/3) [prefer\_lateral\_join\_for\_many\_to\_many?(data\_layer)](Ash.DataLayer.html#prefer_lateral_join_for_many_to_many?/1) Whether or not lateral joins should be used for many to many relationships by default [prefer\_transaction?(resource)](Ash.DataLayer.html#prefer_transaction?/1) [prefer\_transaction\_for\_atomic\_updates?(resource)](Ash.DataLayer.html#prefer_transaction_for_atomic_updates?/1) [resource\_to\_query(resource, domain)](Ash.DataLayer.html#resource_to_query/2) [return\_query(query, resource)](Ash.DataLayer.html#return_query/2) [rollback(resource, term)](Ash.DataLayer.html#rollback/2) Rolls back the current transaction [run\_aggregate\_query(query, aggregates, resource)](Ash.DataLayer.html#run_aggregate_query/3) [run\_aggregate\_query\_with\_lateral\_join(query, aggregates, root\_data, destination\_resource, path)](Ash.DataLayer.html#run_aggregate_query_with_lateral_join/5) [run\_query(query, central\_resource)](Ash.DataLayer.html#run_query/2) [run\_query\_with\_lateral\_join(query, root\_data, destination\_resource, path)](Ash.DataLayer.html#run_query_with_lateral_join/4) [select(query, select, resource)](Ash.DataLayer.html#select/3) [set\_context(resource, query, map)](Ash.DataLayer.html#set_context/3) [set\_tenant(resource, query, term)](Ash.DataLayer.html#set_tenant/3) [sort(query, sort, resource)](Ash.DataLayer.html#sort/3) [source(resource)](Ash.DataLayer.html#source/1) [transaction(resource\_or\_resources, func, timeout \\\\ nil, reason \\\\ %{type: :custom, metadata: %{}})](Ash.DataLayer.html#transaction/4) Wraps the execution of the function in a transaction with the resource's data\_layer [transform\_query(query)](Ash.DataLayer.html#transform_query/1) [update(resource, changeset)](Ash.DataLayer.html#update/2) [update\_query(query, changeset, opts)](Ash.DataLayer.html#update_query/3) [upsert(resource, changeset, keys, identity \\\\ nil)](Ash.DataLayer.html#upsert/4) # [](Ash.DataLayer.html#types)Types [](Ash.DataLayer.html#t:bulk_create_options/0) # bulk\_create\_options() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L167) ``` @type bulk_create_options() :: %{ batch_size: pos_integer(), return_records?: boolean(), upsert?: boolean(), action_select: [atom()], upsert_keys: nil | [atom()], upsert_condition: Ash.Expr.t() | nil, identity: Ash.Resource.Identity.t() | nil, select: [atom()], upsert_fields: nil | [atom()] | :replace_all | {:replace, [atom()]} | {:replace_all_except, [atom()]}, tenant: term() } ``` [](Ash.DataLayer.html#t:bulk_update_options/0) # bulk\_update\_options() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L185) ``` @type bulk_update_options() :: %{ return_records?: boolean(), action_select: [atom()], calculations: [{Ash.Query.Calculation.t(), Ash.Expr.t()}], select: [atom()], tenant: term() } ``` [](Ash.DataLayer.html#t:data_layer_query/0) # data\_layer\_query() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L9) ``` @type data_layer_query() :: struct() ``` [](Ash.DataLayer.html#t:feature/0) # feature() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L68) ``` @type feature() :: :transact | :multitenancy | {:atomic, :update} | {:atomic, :upsert} | {:lateral_join, [Ash.Resource.t()]} | {:join, Ash.Resource.t()} | {:aggregate, Ash.Query.Aggregate.kind()} | {:aggregate_relationship, Ash.Resource.Relationships.relationship()} | {:query_aggregate, Ash.Query.Aggregate.kind()} | :select | :expr_error | :expression_calculation_sort | :aggregate_filter | :aggregate_sort | :boolean_filter | :async_engine | :bulk_create | :update_query | :destroy_query | :create | :read | :update | :destroy | :limit | :offset | :transact | :filter | :composite_type | {:lock, lock_type()} | {:filter_expr, struct()} | {:filter_relationship, Ash.Resource.Relationships.relationship()} | :sort | {:sort, Ash.Type.t()} | :upsert | :composite_primary_key ``` [](Ash.DataLayer.html#t:lateral_join_link/0) # lateral\_join\_link() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L105) ``` @type lateral_join_link() :: {Ash.Resource.t(), atom(), atom(), Ash.Resource.Relationships.relationship()} ``` [](Ash.DataLayer.html#t:lock_type/0) # lock\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L10) ``` @type lock_type() :: :for_update | term() ``` [](Ash.DataLayer.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L8) ``` @type t() :: module() ``` [](Ash.DataLayer.html#t:transaction_reason/0) # transaction\_reason() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L11) ``` @type transaction_reason() :: %{ :type => :create, :metadata => %{resource: Ash.Resource.t(), action: atom()}, optional(:data_layer_context) => %{} } | %{ :type => :update, :metadata => %{ resource: Ash.Resource.t(), action: atom(), record: Ash.Resource.record(), actor: term() }, optional(:data_layer_context) => %{} } | %{ :type => :destroy, :metadata => %{ resource: Ash.Resource.t(), action: atom(), record: Ash.Resource.record(), actor: term() }, optional(:data_layer_context) => %{} } | %{ :type => :read, :metadata => %{ resource: Ash.Resource.t(), query: Ash.Query.t(), actor: term() }, optional(:data_layer_context) => %{} } | %{ :type => :flow_transaction, :metadata => %{ resource: Ash.Resource.t(), input: Ash.ActionInput.t(), action: atom(), actor: term() }, optional(:data_layer_context) => %{} } | %{ :type => :generic, :metadata => %{ step_name: atom() | [term()], flow: module(), actor: term() }, optional(:data_layer_context) => %{} } | %{type: :custom, metadata: map()} | %{type: atom(), metadata: map()} ``` # [](Ash.DataLayer.html#callbacks)Callbacks [](Ash.DataLayer.html#c:add_aggregate/3) # add\_aggregate(data\_layer\_query, t, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L243) ``` @callback add_aggregate( data_layer_query(), Ash.Query.Aggregate.t(), Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:add_aggregates/3) # add\_aggregates(data\_layer\_query, list, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L250) ``` @callback add_aggregates( data_layer_query(), [Ash.Query.Aggregate.t()], Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:add_calculation/4) # add\_calculation(data\_layer\_query, t, expression, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L257) ``` @callback add_calculation( data_layer_query(), Ash.Query.Calculation.t(), expression :: any(), Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:add_calculations/3) # add\_calculations(data\_layer\_query, list, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L265) ``` @callback add_calculations( data_layer_query(), [{Ash.Query.Calculation.t(), expression :: any()}], Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:bulk_create/3) # bulk\_create(t, t, options) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L193) ``` @callback bulk_create( Ash.Resource.t(), Enumerable.t(Ash.Changeset.t()), options :: bulk_create_options() ) :: :ok | {:ok, Enumerable.t(Ash.Resource.record())} | {:error, Ash.Error.t()} | {:error, :no_rollback, Ash.Error.t()} ``` [](Ash.DataLayer.html#c:calculate/3) # calculate(t, list, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L282) ``` @callback calculate(Ash.Resource.t(), [Ash.Expr.t()], context :: map()) :: {:ok, term()} | {:error, term()} ``` [](Ash.DataLayer.html#c:can?/2) # can?(arg1, feature) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L286) ``` @callback can?(Ash.Resource.t() | Spark.Dsl.t(), feature()) :: boolean() ``` [](Ash.DataLayer.html#c:create/2) # create(t, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L202) ``` @callback create(Ash.Resource.t(), Ash.Changeset.t()) :: {:ok, Ash.Resource.record()} | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#c:destroy/2) # destroy(t, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L271) ``` @callback destroy(Ash.Resource.t(), Ash.Changeset.t()) :: :ok | {:error, term()} ``` [](Ash.DataLayer.html#c:destroy_query/4) # destroy\_query(data\_layer\_query, t, t, opts) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L232) ``` @callback destroy_query( data_layer_query(), Ash.Changeset.t(), Ash.Resource.t(), opts :: bulk_update_options() ) :: :ok | {:ok, Enumerable.t(Ash.Resource.record())} | {:error, Ash.Error.t()} | {:error, :no_rollback, Ash.Error.t()} ``` [](Ash.DataLayer.html#c:distinct/3) # distinct(data\_layer\_query, list, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L115) ``` @callback distinct(data_layer_query(), [atom()], resource :: Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:distinct_sort/3) # distinct\_sort(data\_layer\_query, t, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L113) ``` @callback distinct_sort(data_layer_query(), Ash.Sort.t(), resource :: Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:filter/3) # filter(data\_layer\_query, t, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L109) ``` @callback filter(data_layer_query(), Ash.Filter.t(), resource :: Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:functions/1) # functions(t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L108) ``` @callback functions(Ash.Resource.t()) :: [module()] ``` [](Ash.DataLayer.html#c:in_transaction?/1) # in\_transaction?(t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L279) ``` @callback in_transaction?(Ash.Resource.t()) :: boolean() ``` [](Ash.DataLayer.html#c:limit/3) # limit(data\_layer\_query, limit, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L118) ``` @callback limit( data_layer_query(), limit :: non_neg_integer(), resource :: Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:lock/3) # lock(data\_layer\_query, lock\_type, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L140) ``` @callback lock(data_layer_query(), lock_type(), resource :: Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:offset/3) # offset(data\_layer\_query, offset, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L124) ``` @callback offset( data_layer_query(), offset :: non_neg_integer(), resource :: Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:prefer_lateral_join_for_many_to_many?/0) # prefer\_lateral\_join\_for\_many\_to\_many?() (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L117) ``` @callback prefer_lateral_join_for_many_to_many?() :: boolean() ``` [](Ash.DataLayer.html#c:prefer_transaction?/1) # prefer\_transaction?(t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L284) ``` @callback prefer_transaction?(Ash.Resource.t()) :: boolean() ``` [](Ash.DataLayer.html#c:prefer_transaction_for_atomic_updates?/1) # prefer\_transaction\_for\_atomic\_updates?(t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L285) ``` @callback prefer_transaction_for_atomic_updates?(Ash.Resource.t()) :: boolean() ``` [](Ash.DataLayer.html#c:resource_to_query/2) # resource\_to\_query(t, t) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L136) ``` @callback resource_to_query(Ash.Resource.t(), Ash.Domain.t()) :: data_layer_query() ``` [](Ash.DataLayer.html#c:return_query/2) # return\_query(data\_layer\_query, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L164) ``` @callback return_query(data_layer_query(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:rollback/2) # rollback(t, term) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L281) ``` @callback rollback(Ash.Resource.t(), term()) :: no_return() ``` [](Ash.DataLayer.html#c:run_aggregate_query/3) # run\_aggregate\_query(data\_layer\_query, list, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L142) ``` @callback run_aggregate_query( data_layer_query(), [Ash.Query.Aggregate.t()], Ash.Resource.t() ) :: {:ok, map()} | {:error, term()} ``` [](Ash.DataLayer.html#c:run_aggregate_query_with_lateral_join/5) # run\_aggregate\_query\_with\_lateral\_join(data\_layer\_query, list, list, destination\_resource, list) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L148) ``` @callback run_aggregate_query_with_lateral_join( data_layer_query(), [Ash.Query.Aggregate.t()], [Ash.Resource.record()], destination_resource :: Ash.Resource.t(), [lateral_join_link()] ) :: {:ok, [Ash.Resource.t()]} | {:error, term()} ``` [](Ash.DataLayer.html#c:run_query/2) # run\_query(data\_layer\_query, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L138) ``` @callback run_query(data_layer_query(), Ash.Resource.t()) :: {:ok, [Ash.Resource.record()]} | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#c:run_query_with_lateral_join/4) # run\_query\_with\_lateral\_join(data\_layer\_query, list, source\_resource, list) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L156) ``` @callback run_query_with_lateral_join( data_layer_query(), [Ash.Resource.record()], source_resource :: Ash.Resource.t(), [lateral_join_link()] ) :: {:ok, [Ash.Resource.record()]} | {:error, term()} ``` [](Ash.DataLayer.html#c:select/3) # select(data\_layer\_query, select, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L129) ``` @callback select( data_layer_query(), select :: [atom()], resource :: Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:set_context/3) # set\_context(t, data\_layer\_query, map) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L287) ``` @callback set_context(Ash.Resource.t(), data_layer_query(), map()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:set_tenant/3) # set\_tenant(t, data\_layer\_query, term) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L134) ``` @callback set_tenant(Ash.Resource.t(), data_layer_query(), term()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:sort/3) # sort(data\_layer\_query, t, resource) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L111) ``` @callback sort(data_layer_query(), Ash.Sort.t(), resource :: Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#c:source/1) # source(t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L280) ``` @callback source(Ash.Resource.t()) :: String.t() ``` [](Ash.DataLayer.html#c:transaction/4) # transaction(t, function, arg3, reason) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L272) ``` @callback transaction( Ash.Resource.t(), (-> term()), nil | pos_integer(), reason :: transaction_reason() ) :: {:ok, term()} | {:error, term()} ``` [](Ash.DataLayer.html#c:transform_query/1) # transform\_query(t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L137) ``` @callback transform_query(Ash.Query.t()) :: Ash.Query.t() ``` [](Ash.DataLayer.html#c:update/2) # update(t, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L218) ``` @callback update(Ash.Resource.t(), Ash.Changeset.t()) :: {:ok, Ash.Resource.record()} | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#c:update_query/4) # update\_query(data\_layer\_query, t, t, opts) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L221) ``` @callback update_query( data_layer_query(), Ash.Changeset.t(), Ash.Resource.t(), opts :: bulk_update_options() ) :: :ok | {:ok, Enumerable.t(Ash.Resource.record())} | {:error, Ash.Error.t()} | {:error, :no_rollback, Ash.Error.t()} ``` [](Ash.DataLayer.html#c:upsert/3) # upsert(t, t, list) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L204) ``` @callback upsert(Ash.Resource.t(), Ash.Changeset.t(), [atom()]) :: {:ok, Ash.Resource.record()} | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#c:upsert/4) # upsert(t, t, list, arg4) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L206) ``` @callback upsert( Ash.Resource.t(), Ash.Changeset.t(), [atom()], Ash.Resource.Identity.t() | nil ) :: {:ok, Ash.Resource.record() | {:upsert_skipped, Ash.Query.t(), (-> {:ok, Ash.Resource.record()} | {:error, term()} | {:error, :no_rollback, term()})}} | {:error, term()} | {:error, :no_rollback, term()} ``` # [](Ash.DataLayer.html#functions)Functions [](Ash.DataLayer.html#add_aggregates/3) # add\_aggregates(query, aggregates, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L696) ``` @spec add_aggregates(data_layer_query(), [Ash.Query.Aggregate.t()], Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#add_calculations/3) # add\_calculations(query, calculations, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L721) ``` @spec add_calculations( data_layer_query(), [{Ash.Query.Calculation.t(), expression :: term()}], Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#bulk_create/3) # bulk\_create(resource, changesets, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L535) ``` @spec bulk_create( Ash.Resource.t(), Enumerable.t(Ash.Changeset.t()), options :: bulk_create_options() ) :: :ok | {:ok, Enumerable.t(Ash.Resource.record())} | {:error, Ash.Error.t()} | {:error, :no_rollback, Ash.Error.t()} ``` [](Ash.DataLayer.html#calculate/3) # calculate(resource, exprs, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L360) ``` @spec calculate(Ash.Resource.t(), [Ash.Expr.t()], context :: map()) :: {:ok, [term()]} | {:error, Ash.Error.t()} ``` [](Ash.DataLayer.html#can?/2) # can?(feature, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L741) ``` @spec can?(feature(), Ash.Resource.t() | Spark.Dsl.t()) :: boolean() ``` [](Ash.DataLayer.html#create/2) # create(resource, changeset) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L509) ``` @spec create(Ash.Resource.t(), Ash.Changeset.t()) :: {:ok, Ash.Resource.record()} | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#data_layer/1) # data\_layer(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L330) ``` @spec data_layer(Ash.Resource.t() | Spark.Dsl.t()) :: t() | nil ``` The data layer of the resource, or nil if it does not have one [](Ash.DataLayer.html#data_layer_can?/2) # data\_layer\_can?(resource, feature) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L346) ``` @spec data_layer_can?(Ash.Resource.t() | Spark.Dsl.t(), feature()) :: boolean() ``` Whether or not the data layer supports a specific feature [](Ash.DataLayer.html#data_layer_functions/1) # data\_layer\_functions(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L354) ``` @spec data_layer_functions(Ash.Resource.t()) :: map() ``` Custom functions supported by the data layer of the resource [](Ash.DataLayer.html#destroy/2) # destroy(resource, changeset) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L541) ``` @spec destroy(Ash.Resource.t(), Ash.Changeset.t()) :: :ok | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#destroy_query/3) # destroy\_query(query, changeset, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L496) ``` @spec destroy_query( data_layer_query(), Ash.Changeset.t(), opts :: bulk_update_options() ) :: :ok | {:ok, Enumerable.t(Ash.Resource.record())} | {:error, Ash.Error.t()} | {:error, :no_rollback, Ash.Error.t()} ``` [](Ash.DataLayer.html#distinct/3) # distinct(query, distinct, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L634) ``` @spec distinct(data_layer_query(), Ash.Sort.t(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#distinct_sort/3) # distinct\_sort(query, sort, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L645) ``` @spec distinct_sort(data_layer_query(), Ash.Sort.t(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#filter/3) # filter(query, filter, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L604) ``` @spec filter(data_layer_query(), Ash.Filter.t(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#functions/1) # functions(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L815) [](Ash.DataLayer.html#in_transaction?/1) # in\_transaction?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L806) [](Ash.DataLayer.html#limit/3) # limit(query, limit, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L656) ``` @spec limit(data_layer_query(), limit :: non_neg_integer(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#lock/3) # lock(query, lock\_type, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L770) ``` @spec lock( data_layer_query(), lock_type :: lock_type() | nil, resource :: Ash.Resource.t() ) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#offset/3) # offset(query, offset, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L669) ``` @spec offset(data_layer_query(), offset :: non_neg_integer(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#prefer_lateral_join_for_many_to_many?/1) # prefer\_lateral\_join\_for\_many\_to\_many?(data\_layer) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L336) ``` @spec prefer_lateral_join_for_many_to_many?(t()) :: boolean() ``` Whether or not lateral joins should be used for many to many relationships by default [](Ash.DataLayer.html#prefer_transaction?/1) # prefer\_transaction?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L365) ``` @spec prefer_transaction?(Ash.Resource.t()) :: boolean() ``` [](Ash.DataLayer.html#prefer_transaction_for_atomic_updates?/1) # prefer\_transaction\_for\_atomic\_updates?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L378) ``` @spec prefer_transaction_for_atomic_updates?(Ash.Resource.t()) :: boolean() ``` [](Ash.DataLayer.html#resource_to_query/2) # resource\_to\_query(resource, domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L464) ``` @spec resource_to_query(Ash.Resource.t(), Ash.Domain.t()) :: data_layer_query() ``` [](Ash.DataLayer.html#return_query/2) # return\_query(query, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L516) ``` @spec return_query(data_layer_query(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#rollback/2) # rollback(resource, term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L455) ``` @spec rollback(Ash.Resource.t() | [Ash.Resource.t()], term()) :: no_return() ``` Rolls back the current transaction [](Ash.DataLayer.html#run_aggregate_query/3) # run\_aggregate\_query(query, aggregates, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L752) ``` @spec run_aggregate_query( data_layer_query(), [Ash.Query.Aggregate.t()], Ash.Resource.t() ) :: {:ok, map()} | {:error, term()} ``` [](Ash.DataLayer.html#run_aggregate_query_with_lateral_join/5) # run\_aggregate\_query\_with\_lateral\_join(query, aggregates, root\_data, destination\_resource, path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L776) [](Ash.DataLayer.html#run_query/2) # run\_query(query, central\_resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L764) ``` @spec run_query(data_layer_query(), central_resource :: Ash.Resource.t()) :: {:ok, [Ash.Resource.record()]} | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#run_query_with_lateral_join/4) # run\_query\_with\_lateral\_join(query, root\_data, destination\_resource, path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L792) [](Ash.DataLayer.html#select/3) # select(query, select, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L682) ``` @spec select(data_layer_query(), select :: [atom()], Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#set_context/3) # set\_context(resource, query, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L592) ``` @spec set_context(Ash.Resource.t(), data_layer_query(), map()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#set_tenant/3) # set\_tenant(resource, query, term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L562) ``` @spec set_tenant(Ash.Resource.t(), data_layer_query(), String.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#sort/3) # sort(query, sort, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L623) ``` @spec sort(data_layer_query(), Ash.Sort.t(), Ash.Resource.t()) :: {:ok, data_layer_query()} | {:error, term()} ``` [](Ash.DataLayer.html#source/1) # source(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L548) ``` @spec source(Ash.Resource.t()) :: String.t() ``` [](Ash.DataLayer.html#transaction/4) # transaction(resource\_or\_resources, func, timeout \\\\ nil, reason \\\\ %{type: :custom, metadata: %{}}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L398) ``` @spec transaction( Ash.Resource.t() | [Ash.Resource.t()], (-> term()), nil | pos_integer(), reason :: transaction_reason() ) :: term() ``` Wraps the execution of the function in a transaction with the resource's data\_layer [](Ash.DataLayer.html#transform_query/1) # transform\_query(query) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L825) [](Ash.DataLayer.html#update/2) # update(resource, changeset) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L470) ``` @spec update(Ash.Resource.t(), Ash.Changeset.t()) :: {:ok, Ash.Resource.record()} | {:error, term()} | {:error, :no_rollback, term()} ``` [](Ash.DataLayer.html#update_query/3) # update\_query(query, changeset, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L480) ``` @spec update_query( data_layer_query(), Ash.Changeset.t(), opts :: bulk_update_options() ) :: :ok | {:ok, Enumerable.t(Ash.Resource.record())} | {:error, Ash.Error.t()} | {:error, :no_rollback, Ash.Error.t()} ``` [](Ash.DataLayer.html#upsert/4) # upsert(resource, changeset, keys, identity \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/data_layer.ex#L579) ``` @spec upsert( Ash.Resource.t(), Ash.Changeset.t(), [atom()], identity :: Ash.Resource.Identity.t() | nil ) :: {:ok, Ash.Resource.record() | {:upsert_skipped, Ash.Query.t(), (-> {:ok, Ash.Resource.record()} | {:error, term()} | {:error, :no_rollback, term()})}} | {:error, term()} | {:error, :no_rollback, term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Mnesia (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/mnesia/mnesia.ex#L1 "View Source") An Mnesia backed Ash Datalayer. In your application initialization, you will need to call `Mnesia.create_schema([node()])`. Additionally, you will want to create your mnesia tables there. This data layer is *unoptimized*, fetching all records from a table and filtering them in memory. For that reason, it is not recommended to use it with large amounts of data. It can be great for prototyping or light usage, though. # [](Ash.DataLayer.Mnesia.html#summary)Summary ## [Functions](Ash.DataLayer.Mnesia.html#functions) [mnesia(body)](Ash.DataLayer.Mnesia.html#mnesia/1) [start(domain, resources \\\\ \[\])](Ash.DataLayer.Mnesia.html#start/2) Creates the table for each mnesia resource in a domain # [](Ash.DataLayer.Mnesia.html#functions)Functions [](Ash.DataLayer.Mnesia.html#mnesia/1) # mnesia(body) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/mnesia/mnesia.ex#L36) [](Ash.DataLayer.Mnesia.html#start/2) # start(domain, resources \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/mnesia/mnesia.ex#L46) Creates the table for each mnesia resource in a domain [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Mnesia.Info (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/mnesia/info.ex#L1 "View Source") Introspection helpers for Ash.DataLayer.Mnesia # [](Ash.DataLayer.Mnesia.Info.html#summary)Summary ## [Functions](Ash.DataLayer.Mnesia.Info.html#functions) [table(resource)](Ash.DataLayer.Mnesia.Info.html#table/1) The mnesia table for a resource # [](Ash.DataLayer.Mnesia.Info.html#functions)Functions [](Ash.DataLayer.Mnesia.Info.html#table/1) # table(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/mnesia/info.ex#L7) The mnesia table for a resource [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Simple (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/simple/simple.ex#L1 "View Source") A data layer that returns structs. This is the data layer that is used under the hood by embedded resources, and resources without data layers. # [](Ash.DataLayer.Simple.html#summary)Summary ## [Functions](Ash.DataLayer.Simple.html#functions) [bulk\_create(resource, stream, options)](Ash.DataLayer.Simple.html#bulk_create/3) Callback implementation for [`Ash.DataLayer.bulk_create/3`](Ash.DataLayer.html#c:bulk_create/3). [set\_data(query, data)](Ash.DataLayer.Simple.html#set_data/2) Sets the data for a query against a data-layer-less resource # [](Ash.DataLayer.Simple.html#functions)Functions [](Ash.DataLayer.Simple.html#bulk_create/3) # bulk\_create(resource, stream, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/simple/simple.ex#L160) Callback implementation for [`Ash.DataLayer.bulk_create/3`](Ash.DataLayer.html#c:bulk_create/3). [](Ash.DataLayer.Simple.html#set_data/2) # set\_data(query, data) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/simple/simple.ex#L49) Sets the data for a query against a data-layer-less resource [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Verifiers.RequirePreCheckWith (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/data_layer/verifiers/require_pre_check_with.ex#L1 "View Source") Ensures that all identities have a `pre_check_with` configured, or raises. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Dsl.ResourceReference (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/dsl.ex#L79 "View Source") A resource reference in a domain # [](Ash.Domain.Dsl.ResourceReference.html#summary)Summary ## [Types](Ash.Domain.Dsl.ResourceReference.html#types) [t()](Ash.Domain.Dsl.ResourceReference.html#t:t/0) # [](Ash.Domain.Dsl.ResourceReference.html#types)Types [](Ash.Domain.Dsl.ResourceReference.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/dsl.ex#L83) ``` @type t() :: %Ash.Domain.Dsl.ResourceReference{ definitions: [ Ash.Resource.Interface.t() | Ash.Resource.CalculationInterface.t() ], resource: module() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/domain.ex#L1 "View Source") A domain allows you to interact with your resources, and holds domain-wide configuration. For example, the json domain extension adds a domain extension that lets you toggle authorization on/off for all resources in a given domain. You include resources in your domain like so: ``` defmodule MyApp.MyDomain do use Ash.Domain resources do resource OneResource resource SecondResource end end ``` ### [](Ash.Domain.html#module-options)Options - `:validate_config_inclusion?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to validate that this domain is included in the configuration. The default value is `true`. - `:backwards_compatible_interface?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to include the 2.0 backwards compatible interface, which includes all of the interaction functions which are now defined on the [`Ash`](Ash.html) module The default value is `true`. - `:extensions` (list of module that adopts [`Spark.Dsl.Extension`](../spark/2.2.40/Spark.Dsl.Extension.html)) - A list of DSL extensions to add to the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html) - `:authorizers` (one or a list of module that adopts [`Ash.Authorizer`](Ash.Authorizer.html)) - authorizers extensions to add to the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html) The default value is `[]`. - `:otp_app` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The otp\_app to use for any application configurable options - `:fragments` (list of [`module/0`](../elixir/typespecs.html#built-in-types)) - Fragments to include in the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html). See the fragments guide for more. # [](Ash.Domain.html#summary)Summary ## [Types](Ash.Domain.html#types) [t()](Ash.Domain.html#t:t/0) # [](Ash.Domain.html#types)Types [](Ash.Domain.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/domain.ex#L45) ``` @type t() :: module() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Igniter (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/igniter.ex#L2 "View Source") Codemods for working with Ash.Domain modules # [](Ash.Domain.Igniter.html#summary)Summary ## [Functions](Ash.Domain.Igniter.html#functions) [add\_resource\_reference(igniter, domain, resource)](Ash.Domain.Igniter.html#add_resource_reference/3) Adds a resource reference to a domain's `resources` block [list\_domains(igniter)](Ash.Domain.Igniter.html#list_domains/1) List all domain modules found in the project [remove\_resource\_reference(igniter, domain, resource)](Ash.Domain.Igniter.html#remove_resource_reference/3) Removes a resource reference from a domain's `resources` block # [](Ash.Domain.Igniter.html#functions)Functions [](Ash.Domain.Igniter.html#add_resource_reference/3) # add\_resource\_reference(igniter, domain, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/igniter.ex#L21) Adds a resource reference to a domain's `resources` block [](Ash.Domain.Igniter.html#list_domains/1) # list\_domains(igniter) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/igniter.ex#L6) List all domain modules found in the project [](Ash.Domain.Igniter.html#remove_resource_reference/3) # remove\_resource\_reference(igniter, domain, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/igniter.ex#L72) Removes a resource reference from a domain's `resources` block [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Info.Diagram (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/diagram.ex#L1 "View Source") Generate Mermaid diagrams from a specified domain. ## [](Ash.Domain.Info.Diagram.html#module-limitations)Limitations We can't easily model Ash relationships with Mermaid diagrams because they are unidirectional and could be asymmetric. Mermaid assumes symmetrical, bidirectional relationships. If we try to model all unidirectional relationships as separate lines in the diagram it gets very hard to read very quickly. # [](Ash.Domain.Info.Diagram.html#summary)Summary ## [Functions](Ash.Domain.Info.Diagram.html#functions) [mermaid\_class\_diagram(domain, opts \\\\ \[indent: " ", show\_private?: false\])](Ash.Domain.Info.Diagram.html#mermaid_class_diagram/2) Generates a Mermaid Class Diagram for a given domain. [mermaid\_er\_diagram(domain, opts \\\\ \[indent: " ", show\_private?: false\])](Ash.Domain.Info.Diagram.html#mermaid_er_diagram/2) Generates a Mermaid Entity Relationship Diagram for a given domain. # [](Ash.Domain.Info.Diagram.html#functions)Functions [](Ash.Domain.Info.Diagram.html#mermaid_class_diagram/2) # mermaid\_class\_diagram(domain, opts \\\\ \[indent: " ", show\_private?: false]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/diagram.ex#L175) Generates a Mermaid Class Diagram for a given domain. Shows only public attributes, calculations, aggregates and actions. Shows a connecting line for relationships with the type of relationship indicated in the attribute list. [](Ash.Domain.Info.Diagram.html#mermaid_er_diagram/2) # mermaid\_er\_diagram(domain, opts \\\\ \[indent: " ", show\_private?: false]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/diagram.ex#L86) Generates a Mermaid Entity Relationship Diagram for a given domain. Shows only public attributes, calculations, aggregates and actions. Shows a one-to-one line for relationships as enumerating all unidirectional relationships is far too noisy. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Info (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L1 "View Source") Introspection tools for Ash.Domain # [](Ash.Domain.Info.html#summary)Summary ## [Functions](Ash.Domain.Info.html#functions) [allow(domain)](Ash.Domain.Info.html#allow/1) The allow MFA for a domain [allow\_unregistered?(domain)](Ash.Domain.Info.html#allow_unregistered?/1) Whether or not the domain allows unregistered resources to be used with it [authorize(domain)](Ash.Domain.Info.html#authorize/1) When authorization should happen for a given domain [depend\_on\_resources(domain)](Ash.Domain.Info.html#depend_on_resources/1) deprecated Gets the resources of a domain module. Can be used at compile time. [description(domain)](Ash.Domain.Info.html#description/1) The description of the domain [find\_manage\_relationships\_with\_identity\_not\_configured(otp\_app)](Ash.Domain.Info.html#find_manage_relationships_with_identity_not_configured/1) [related\_domain(subject, relationship, default \\\\ nil)](Ash.Domain.Info.html#related_domain/3) Determine what domain to use when interacting with a related resource. [require\_actor?(domain)](Ash.Domain.Info.html#require_actor?/1) Whether or not the actor is always required for a domain [resource(domain, resource)](Ash.Domain.Info.html#resource/2) Returns `{:ok, resource}` if the resource can be used by the domain, or `{:error, error}`. [resource\_references(domain)](Ash.Domain.Info.html#resource_references/1) Gets the resource references of a domain module. DO NOT USE AT COMPILE TIME. [resources(domain)](Ash.Domain.Info.html#resources/1) Gets the resources of a domain module. [short\_name(domain)](Ash.Domain.Info.html#short_name/1) The short name for a domain [span\_name(domain, resource, action)](Ash.Domain.Info.html#span_name/3) The span\_name for a domain and resource combination [telemetry\_event\_name(domain, name)](Ash.Domain.Info.html#telemetry_event_name/2) Names a telemetry event for a given domain/resource combo [timeout(domain)](Ash.Domain.Info.html#timeout/1) The execution timeout for a domain [trace\_name(domain)](Ash.Domain.Info.html#trace_name/1) The trace name for a domain # [](Ash.Domain.Info.html#functions)Functions [](Ash.Domain.Info.html#allow/1) # allow(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L197) ``` @spec allow(Ash.Domain.t() | Spark.Dsl.t()) :: mfa() | nil ``` The allow MFA for a domain [](Ash.Domain.Info.html#allow_unregistered?/1) # allow\_unregistered?(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L245) ``` @spec allow_unregistered?(Ash.Domain.t() | Spark.Dsl.t()) :: atom() | nil ``` Whether or not the domain allows unregistered resources to be used with it [](Ash.Domain.Info.html#authorize/1) # authorize(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L239) ``` @spec authorize(Ash.Domain.t()) :: :always | :by_default | :when_requested ``` When authorization should happen for a given domain [](Ash.Domain.Info.html#depend_on_resources/1) # depend\_on\_resources(domain) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L174) This macro is deprecated. Use \`Ash.Domain.Info.resources/1\` instead. This macro is no longer necessary. ``` @spec depend_on_resources(Macro.t()) :: Macro.t() ``` Gets the resources of a domain module. Can be used at compile time. Liberal use of this can greatly increase compile times, or even cause compiler deadlocks. Use with care. [](Ash.Domain.Info.html#description/1) # description(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L191) ``` @spec description(Spark.Dsl.t() | Ash.Domain.t()) :: String.t() | nil ``` The description of the domain [](Ash.Domain.Info.html#find_manage_relationships_with_identity_not_configured/1) # find\_manage\_relationships\_with\_identity\_not\_configured(otp\_app) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L106) [](Ash.Domain.Info.html#related_domain/3) # related\_domain(subject, relationship, default \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L46) ``` @spec related_domain( Ash.Resource.t() | Ash.Query.t() | Ash.Changeset.t() | Ash.ActionInput.t(), atom() | Ash.Resource.Relationships.relationship() | [atom() | Ash.Resource.Relationships.relationship()], Ash.Domain.t() | nil ) :: Ash.Domain.t() ``` Determine what domain to use when interacting with a related resource. We choose the first domain found in the following order: - `relationship.domain`, i.e an explicitly configured domain for a relationship - `resource.domain`, i.e. the domain the resource declares - `subject.domain`, i.e. the domain of the query, changeset or action input (if it has one) - `default`, the default domain provided as the third argument [](Ash.Domain.Info.html#require_actor?/1) # require\_actor?(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L233) ``` @spec require_actor?(Ash.Domain.t()) :: boolean() ``` Whether or not the actor is always required for a domain [](Ash.Domain.Info.html#resource/2) # resource(domain, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L254) ``` @spec resource(Ash.Domain.t() | Spark.Dsl.t(), Ash.Resource.t()) :: {:ok, Ash.Resource.t()} | {:error, Ash.Error.t()} ``` Returns `{:ok, resource}` if the resource can be used by the domain, or `{:error, error}`. [](Ash.Domain.Info.html#resource_references/1) # resource\_references(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L25) ``` @spec resource_references(Spark.Dsl.t() | Ash.Domain.t()) :: [ Ash.Domain.Dsl.ResourceReference.t() ] ``` Gets the resource references of a domain module. DO NOT USE AT COMPILE TIME. If you need the resource list at compile time, use [`depend_on_resources/1`](Ash.Domain.Info.html#depend_on_resources/1) [](Ash.Domain.Info.html#resources/1) # resources(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L12) ``` @spec resources(Spark.Dsl.t() | Ash.Domain.t()) :: [Ash.Resource.t()] ``` Gets the resources of a domain module. [](Ash.Domain.Info.html#short_name/1) # short\_name(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L209) ``` @spec short_name(Ash.Domain.t()) :: atom() ``` The short name for a domain [](Ash.Domain.Info.html#span_name/3) # span\_name(domain, resource, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L221) ``` @spec span_name(Ash.Domain.t(), Ash.Resource.t(), action :: atom() | binary()) :: String.t() ``` The span\_name for a domain and resource combination [](Ash.Domain.Info.html#telemetry_event_name/2) # telemetry\_event\_name(domain, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L227) ``` @spec telemetry_event_name(Ash.Domain.t(), atom() | [atom()]) :: [atom()] ``` Names a telemetry event for a given domain/resource combo [](Ash.Domain.Info.html#timeout/1) # timeout(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L203) ``` @spec timeout(Ash.Domain.t()) :: nil | :infinity | integer() ``` The execution timeout for a domain [](Ash.Domain.Info.html#trace_name/1) # trace\_name(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info.ex#L215) ``` @spec trace_name(Ash.Domain.t()) :: String.t() ``` The trace name for a domain [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Info.Livebook (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L1 "View Source") Generate a Livebook from a specified domain. # [](Ash.Domain.Info.Livebook.html#summary)Summary ## [Functions](Ash.Domain.Info.Livebook.html#functions) [action\_header()](Ash.Domain.Info.Livebook.html#action_header/0) [action\_input\_section(resource, action)](Ash.Domain.Info.Livebook.html#action_input_section/2) [action\_section(resource, action)](Ash.Domain.Info.Livebook.html#action_section/2) [attr\_header()](Ash.Domain.Info.Livebook.html#attr_header/0) [attr\_section(attr)](Ash.Domain.Info.Livebook.html#attr_section/1) [domain\_section(domain)](Ash.Domain.Info.Livebook.html#domain_section/1) [overview(domains)](Ash.Domain.Info.Livebook.html#overview/1) [resource\_section(resource)](Ash.Domain.Info.Livebook.html#resource_section/1) # [](Ash.Domain.Info.Livebook.html#functions)Functions [](Ash.Domain.Info.Livebook.html#action_header/0) # action\_header() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L99) [](Ash.Domain.Info.Livebook.html#action_input_section/2) # action\_input\_section(resource, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L110) [](Ash.Domain.Info.Livebook.html#action_section/2) # action\_section(resource, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L106) [](Ash.Domain.Info.Livebook.html#attr_header/0) # attr\_header() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L88) [](Ash.Domain.Info.Livebook.html#attr_section/1) # attr\_section(attr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L95) [](Ash.Domain.Info.Livebook.html#domain_section/1) # domain\_section(domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L37) [](Ash.Domain.Info.Livebook.html#overview/1) # overview(domains) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L29) [](Ash.Domain.Info.Livebook.html#resource_section/1) # resource\_section(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/info/livebook.ex#L66) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Verifiers.EnsureNoEmbeds (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/verifiers/ensure_no_embeds.ex#L1 "View Source") Ensures that all resources for a given domain are not embeds. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Verifiers.ValidateArgumentsToCodeInterface (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/verifiers/validate_arguments_to_code_interface.ex#L1 "View Source") Validate the arguments defined in the code interface and reject arguments that are not action attributes/arguments [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain.Verifiers.ValidateRelatedResourceInclusion (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/domain/verifiers/validate_related_resource_inclusion.ex#L1 "View Source") Ensures that all related resources are included in a domain. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Action.InvalidArgument exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/action/invalid_argument.ex#L1 "View Source") Used when an invalid value is provided for an action argument # [](Ash.Error.Action.InvalidArgument.html#summary)Summary ## [Functions](Ash.Error.Action.InvalidArgument.html#functions) [exception()](Ash.Error.Action.InvalidArgument.html#exception/0) # [](Ash.Error.Action.InvalidArgument.html#functions)Functions [](Ash.Error.Action.InvalidArgument.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/action/invalid_argument.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.ActionRequiresActor exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/action_requires_actor.ex#L1 "View Source") Used when an actor is referenced in a filter template, but no actor exists # [](Ash.Error.Changes.ActionRequiresActor.html#summary)Summary ## [Functions](Ash.Error.Changes.ActionRequiresActor.html#functions) [exception()](Ash.Error.Changes.ActionRequiresActor.html#exception/0) # [](Ash.Error.Changes.ActionRequiresActor.html#functions)Functions [](Ash.Error.Changes.ActionRequiresActor.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/action_requires_actor.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.InvalidArgument exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_argument.ex#L1 "View Source") Used when an invalid value is provided for an action argument # [](Ash.Error.Changes.InvalidArgument.html#summary)Summary ## [Functions](Ash.Error.Changes.InvalidArgument.html#functions) [exception()](Ash.Error.Changes.InvalidArgument.html#exception/0) # [](Ash.Error.Changes.InvalidArgument.html#functions)Functions [](Ash.Error.Changes.InvalidArgument.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_argument.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.InvalidAttribute exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_attribute.ex#L1 "View Source") Used when an invalid value is provided for an attribute change # [](Ash.Error.Changes.InvalidAttribute.html#summary)Summary ## [Functions](Ash.Error.Changes.InvalidAttribute.html#functions) [exception()](Ash.Error.Changes.InvalidAttribute.html#exception/0) # [](Ash.Error.Changes.InvalidAttribute.html#functions)Functions [](Ash.Error.Changes.InvalidAttribute.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_attribute.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.InvalidChanges exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_changes.ex#L1 "View Source") Used when a change is provided that covers multiple attributes/relationships # [](Ash.Error.Changes.InvalidChanges.html#summary)Summary ## [Functions](Ash.Error.Changes.InvalidChanges.html#functions) [exception()](Ash.Error.Changes.InvalidChanges.html#exception/0) # [](Ash.Error.Changes.InvalidChanges.html#functions)Functions [](Ash.Error.Changes.InvalidChanges.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_changes.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.InvalidRelationship exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_relationship.ex#L1 "View Source") Used when an invalid value is provided for a relationship change # [](Ash.Error.Changes.InvalidRelationship.html#summary)Summary ## [Functions](Ash.Error.Changes.InvalidRelationship.html#functions) [exception()](Ash.Error.Changes.InvalidRelationship.html#exception/0) # [](Ash.Error.Changes.InvalidRelationship.html#functions)Functions [](Ash.Error.Changes.InvalidRelationship.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/invalid_relationship.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.NoSuchAttribute exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/no_such_attribute.ex#L1 "View Source") Used when a change is provided for an attribute that does not exist # [](Ash.Error.Changes.NoSuchAttribute.html#summary)Summary ## [Functions](Ash.Error.Changes.NoSuchAttribute.html#functions) [exception()](Ash.Error.Changes.NoSuchAttribute.html#exception/0) # [](Ash.Error.Changes.NoSuchAttribute.html#functions)Functions [](Ash.Error.Changes.NoSuchAttribute.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/no_such_attribute.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.NoSuchRelationship exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/no_such_relationship.ex#L1 "View Source") Used when a change is provided for an relationship that does not exist # [](Ash.Error.Changes.NoSuchRelationship.html#summary)Summary ## [Functions](Ash.Error.Changes.NoSuchRelationship.html#functions) [exception()](Ash.Error.Changes.NoSuchRelationship.html#exception/0) # [](Ash.Error.Changes.NoSuchRelationship.html#functions)Functions [](Ash.Error.Changes.NoSuchRelationship.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/no_such_relationship.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.Required exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/required.ex#L1 "View Source") Used when an attribute or relationship is required # [](Ash.Error.Changes.Required.html#summary)Summary ## [Functions](Ash.Error.Changes.Required.html#functions) [exception()](Ash.Error.Changes.Required.html#exception/0) # [](Ash.Error.Changes.Required.html#functions)Functions [](Ash.Error.Changes.Required.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/required.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Changes.StaleRecord exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/stale_record.ex#L1 "View Source") Used when a stale record is attempted to be updated or deleted # [](Ash.Error.Changes.StaleRecord.html#summary)Summary ## [Functions](Ash.Error.Changes.StaleRecord.html#functions) [exception()](Ash.Error.Changes.StaleRecord.html#exception/0) # [](Ash.Error.Changes.StaleRecord.html#functions)Functions [](Ash.Error.Changes.StaleRecord.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/changes/stale_record.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/exception.ex#L1 "View Source") Tooling for creating an Ash exception # [](Ash.Error.Exception.html#summary)Summary ## [Functions](Ash.Error.Exception.html#functions) [def\_ash\_error(fields, opts \\\\ \[\])](Ash.Error.Exception.html#def_ash_error/2) # [](Ash.Error.Exception.html#functions)Functions [](Ash.Error.Exception.html#def_ash_error/2) # def\_ash\_error(fields, opts \\\\ \[]) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/exception.ex#L10) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.CannotFilterCreates exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/cannot_filter_creates.ex#L1 "View Source") Used when a create action would be filtered # [](Ash.Error.Forbidden.CannotFilterCreates.html#summary)Summary ## [Functions](Ash.Error.Forbidden.CannotFilterCreates.html#functions) [exception()](Ash.Error.Forbidden.CannotFilterCreates.html#exception/0) # [](Ash.Error.Forbidden.CannotFilterCreates.html#functions)Functions [](Ash.Error.Forbidden.CannotFilterCreates.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/cannot_filter_creates.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.DomainRequiresActor exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/domain_requires_actor.ex#L1 "View Source") Used when a domain that has `require_actor? true` is provided no actor # [](Ash.Error.Forbidden.DomainRequiresActor.html#summary)Summary ## [Functions](Ash.Error.Forbidden.DomainRequiresActor.html#functions) [exception()](Ash.Error.Forbidden.DomainRequiresActor.html#exception/0) # [](Ash.Error.Forbidden.DomainRequiresActor.html#functions)Functions [](Ash.Error.Forbidden.DomainRequiresActor.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/domain_requires_actor.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.DomainRequiresAuthorization exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/domain_requires_authorization.ex#L1 "View Source") Used when a domain that has `authorize :always` is provided authorize?: false # [](Ash.Error.Forbidden.DomainRequiresAuthorization.html#summary)Summary ## [Functions](Ash.Error.Forbidden.DomainRequiresAuthorization.html#functions) [exception()](Ash.Error.Forbidden.DomainRequiresAuthorization.html#exception/0) # [](Ash.Error.Forbidden.DomainRequiresAuthorization.html#functions)Functions [](Ash.Error.Forbidden.DomainRequiresAuthorization.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/domain_requires_authorization.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.ForbiddenField exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/forbidden_field.ex#L1 "View Source") Raised in cases where access to a specific field was prevented # [](Ash.Error.Forbidden.ForbiddenField.html#summary)Summary ## [Functions](Ash.Error.Forbidden.ForbiddenField.html#functions) [exception()](Ash.Error.Forbidden.ForbiddenField.html#exception/0) # [](Ash.Error.Forbidden.ForbiddenField.html#functions)Functions [](Ash.Error.Forbidden.ForbiddenField.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/forbidden_field.ex#L6) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden.ex#L1 "View Source") Used when authorization for an action fails # [](Ash.Error.Forbidden.html#summary)Summary ## [Types](Ash.Error.Forbidden.html#types) [t()](Ash.Error.Forbidden.html#t:t/0) ## [Functions](Ash.Error.Forbidden.html#functions) [exception()](Ash.Error.Forbidden.html#exception/0) [message(map)](Ash.Error.Forbidden.html#message/1) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). # [](Ash.Error.Forbidden.html#types)Types [](Ash.Error.Forbidden.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden.ex#L5) ``` @type t() :: %Ash.Error.Forbidden{ __exception__: true, action_input: Ash.ActionInput.t() | nil, bread_crumbs: term(), changeset: Ash.Changeset.t() | nil, class: term(), errors: term(), path: term(), query: Ash.Query.t() | nil, splode: term(), stacktrace: term(), vars: term() } ``` # [](Ash.Error.Forbidden.html#functions)Functions [](Ash.Error.Forbidden.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden.ex#L3) [](Ash.Error.Forbidden.html#message/1) # message(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden.ex#L3) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.InitialDataRequired exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/initial_data_required.ex#L1 "View Source") Used when initial data was not supplied when it was required # [](Ash.Error.Forbidden.InitialDataRequired.html#summary)Summary ## [Functions](Ash.Error.Forbidden.InitialDataRequired.html#functions) [exception()](Ash.Error.Forbidden.InitialDataRequired.html#exception/0) # [](Ash.Error.Forbidden.InitialDataRequired.html#functions)Functions [](Ash.Error.Forbidden.InitialDataRequired.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/initial_data_required.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.MustPassStrictCheck exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/must_pass_strict_check.ex#L1 "View Source") Used when unreachable code/conditions are reached in the framework # [](Ash.Error.Forbidden.MustPassStrictCheck.html#summary)Summary ## [Functions](Ash.Error.Forbidden.MustPassStrictCheck.html#functions) [exception()](Ash.Error.Forbidden.MustPassStrictCheck.html#exception/0) # [](Ash.Error.Forbidden.MustPassStrictCheck.html#functions)Functions [](Ash.Error.Forbidden.MustPassStrictCheck.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/must_pass_strict_check.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.Placeholder exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/placeholder.ex#L1 "View Source") A placeholder exception that the user should never see # [](Ash.Error.Forbidden.Placeholder.html#summary)Summary ## [Functions](Ash.Error.Forbidden.Placeholder.html#functions) [exception()](Ash.Error.Forbidden.Placeholder.html#exception/0) # [](Ash.Error.Forbidden.Placeholder.html#functions)Functions [](Ash.Error.Forbidden.Placeholder.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/placeholder.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Forbidden.Policy exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/policy.ex#L1 "View Source") Raised when policy authorization for an action fails # [](Ash.Error.Forbidden.Policy.html#summary)Summary ## [Functions](Ash.Error.Forbidden.Policy.html#functions) [exception()](Ash.Error.Forbidden.Policy.html#exception/0) [get\_breakdown(facts, filter, policies, opts \\\\ \[\])](Ash.Error.Forbidden.Policy.html#get_breakdown/4) Print a report of an authorization failure from authorization information. [report(forbidden)](Ash.Error.Forbidden.Policy.html#report/1) Print a report of an authorization failure from a forbidden error [report(error, opts \\\\ \[\])](Ash.Error.Forbidden.Policy.html#report/2) # [](Ash.Error.Forbidden.Policy.html#functions)Functions [](Ash.Error.Forbidden.Policy.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/policy.ex#L9) [](Ash.Error.Forbidden.Policy.html#get_breakdown/4) # get\_breakdown(facts, filter, policies, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/policy.ex#L137) Print a report of an authorization failure from authorization information. Options: - `:help_text?`: Defaults to true. Displays help text at the top of the policy breakdown. - `:success?`: Defaults to false. Changes the messaging/graphics around to indicate successful policy authorization. - `:must_pass_strict_check?`: Defaults to false. Adds a message about this authorization requiring passing strict check. [](Ash.Error.Forbidden.Policy.html#report/1) # report(forbidden) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/policy.ex#L81) Print a report of an authorization failure from a forbidden error Options: - `:help_text?`: Defaults to true. Displays help text at the top of the policy breakdown. [](Ash.Error.Forbidden.Policy.html#report/2) # report(error, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/forbidden/policy.ex#L87) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Framework.AssumptionFailed exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/assumption_failed.ex#L1 "View Source") Used when unreachable code/conditions are reached in the framework # [](Ash.Error.Framework.AssumptionFailed.html#summary)Summary ## [Functions](Ash.Error.Framework.AssumptionFailed.html#functions) [exception()](Ash.Error.Framework.AssumptionFailed.html#exception/0) # [](Ash.Error.Framework.AssumptionFailed.html#functions)Functions [](Ash.Error.Framework.AssumptionFailed.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/assumption_failed.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Framework.CanNotBeAtomic exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/can_not_be_atomic.ex#L1 "View Source") Used when a change that is only atomic cannot be done atomically # [](Ash.Error.Framework.CanNotBeAtomic.html#summary)Summary ## [Functions](Ash.Error.Framework.CanNotBeAtomic.html#functions) [exception()](Ash.Error.Framework.CanNotBeAtomic.html#exception/0) # [](Ash.Error.Framework.CanNotBeAtomic.html#functions)Functions [](Ash.Error.Framework.CanNotBeAtomic.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/can_not_be_atomic.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Framework.FlagAssertionFailed exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/flag_assertion_failed.ex#L1 "View Source") Used when unreachable code/conditions are reached in the framework # [](Ash.Error.Framework.FlagAssertionFailed.html#summary)Summary ## [Functions](Ash.Error.Framework.FlagAssertionFailed.html#functions) [exception()](Ash.Error.Framework.FlagAssertionFailed.html#exception/0) # [](Ash.Error.Framework.FlagAssertionFailed.html#functions)Functions [](Ash.Error.Framework.FlagAssertionFailed.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/flag_assertion_failed.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Framework exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework.ex#L1 "View Source") Used when an unknown/generic framework error occurs # [](Ash.Error.Framework.html#summary)Summary ## [Types](Ash.Error.Framework.html#types) [t()](Ash.Error.Framework.html#t:t/0) ## [Functions](Ash.Error.Framework.html#functions) [exception()](Ash.Error.Framework.html#exception/0) [message(map)](Ash.Error.Framework.html#message/1) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). # [](Ash.Error.Framework.html#types)Types [](Ash.Error.Framework.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework.ex#L5) ``` @type t() :: %Ash.Error.Framework{ __exception__: true, action_input: Ash.ActionInput.t() | nil, bread_crumbs: term(), changeset: Ash.Changeset.t() | nil, class: term(), errors: term(), path: term(), query: Ash.Query.t() | nil, splode: term(), stacktrace: term(), vars: term() } ``` # [](Ash.Error.Framework.html#functions)Functions [](Ash.Error.Framework.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework.ex#L3) [](Ash.Error.Framework.html#message/1) # message(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework.ex#L3) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Framework.InvalidReturnType exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/invalid_return_type.ex#L1 "View Source") Used when a callback returns an invalid type # [](Ash.Error.Framework.InvalidReturnType.html#summary)Summary ## [Functions](Ash.Error.Framework.InvalidReturnType.html#functions) [exception()](Ash.Error.Framework.InvalidReturnType.html#exception/0) # [](Ash.Error.Framework.InvalidReturnType.html#functions)Functions [](Ash.Error.Framework.InvalidReturnType.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/invalid_return_type.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Framework.MustBeAtomic exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/must_be_atomic.ex#L1 "View Source") Used when an action that must be atomic cannot be done atomically # [](Ash.Error.Framework.MustBeAtomic.html#summary)Summary ## [Functions](Ash.Error.Framework.MustBeAtomic.html#functions) [exception()](Ash.Error.Framework.MustBeAtomic.html#exception/0) # [](Ash.Error.Framework.MustBeAtomic.html#functions)Functions [](Ash.Error.Framework.MustBeAtomic.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/must_be_atomic.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Framework.SynchronousEngineStuck exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/synchronous_engine_stuck.ex#L1 "View Source") Used when the sycnrhonous engine cannot proceed # [](Ash.Error.Framework.SynchronousEngineStuck.html#summary)Summary ## [Functions](Ash.Error.Framework.SynchronousEngineStuck.html#functions) [exception()](Ash.Error.Framework.SynchronousEngineStuck.html#exception/0) # [](Ash.Error.Framework.SynchronousEngineStuck.html#functions)Functions [](Ash.Error.Framework.SynchronousEngineStuck.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/framework/synchronous_engine_stuck.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L1 "View Source") Tools and utilities used by Ash to manage and conform errors # [](Ash.Error.html#summary)Summary ## [Types](Ash.Error.html#types) [ash\_error()](Ash.Error.html#t:ash_error/0) [ash\_error\_subject()](Ash.Error.html#t:ash_error_subject/0) [class()](Ash.Error.html#t:class/0) [class\_module()](Ash.Error.html#t:class_module/0) [error\_class()](Ash.Error.html#t:error_class/0) [error\_input()](Ash.Error.html#t:error_input/0) [error\_keyword()](Ash.Error.html#t:error_keyword/0) [error\_keyword\_option()](Ash.Error.html#t:error_keyword_option/0) [path()](Ash.Error.html#t:path/0) [path\_input()](Ash.Error.html#t:path_input/0) [t()](Ash.Error.html#t:t/0) ## [Functions](Ash.Error.html#functions) [ash\_error?(value)](Ash.Error.html#ash_error?/1) Returns whether or not a term is an Ash.Error type. [error\_descriptions(errors)](Ash.Error.html#error_descriptions/1) Converts errors into a single `String.t`. [set\_path(errors, path)](Ash.Error.html#set_path/2) This function prepends the provided path to any existing path on the errors. [splode\_error?(arg1, splode)](Ash.Error.html#splode_error?/2) [to\_ash\_error(value, stacktrace \\\\ nil, opts \\\\ \[\])](Ash.Error.html#to_ash_error/3) Converts a value to an Ash exception. [to\_error\_class(value, opts \\\\ \[\])](Ash.Error.html#to_error_class/2) Converts a value to an Ash.Error type. [unwrap!(result, opts \\\\ nil)](Ash.Error.html#unwrap!/2) Raises an error if the result is an error, otherwise returns the result # [](Ash.Error.html#types)Types [](Ash.Error.html#t:ash_error/0) # ash\_error() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L23) ``` @type ash_error() :: Exception.t() ``` [](Ash.Error.html#t:ash_error_subject/0) # ash\_error\_subject() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L24) ``` @type ash_error_subject() :: Ash.Changeset.t() | Ash.Query.t() | Ash.ActionInput.t() ``` [](Ash.Error.html#t:class/0) # class() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L5) ``` @type class() :: %{ :__struct__ => class_module(), :__exception__ => true, :errors => [t()], :class => error_class(), :bread_crumbs => [String.t()], :vars => Keyword.t(), :stacktrace => Splode.Stacktrace.t() | nil, :context => map(), optional(atom()) => any() } ``` [](Ash.Error.html#t:class_module/0) # class\_module() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L5) ``` @type class_module() :: Ash.Error.Unknown | Ash.Error.Framework | Ash.Error.Invalid | Ash.Error.Forbidden ``` [](Ash.Error.html#t:error_class/0) # error\_class() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L5) ``` @type error_class() :: :unknown | :framework | :invalid | :forbidden ``` [](Ash.Error.html#t:error_input/0) # error\_input() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L28) ``` @type error_input() :: ash_error() | error_keyword() | String.t() | ash_error_subject() | Exception.t() | any() ``` [](Ash.Error.html#t:error_keyword/0) # error\_keyword() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L21) ``` @type error_keyword() :: [error_keyword_option()] ``` [](Ash.Error.html#t:error_keyword_option/0) # error\_keyword\_option() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L14) ``` @type error_keyword_option() :: {:field, atom()} | {:fields, [atom()]} | {:value, term()} | {:message, String.t()} | {:path, [atom() | String.t()]} ``` [](Ash.Error.html#t:path/0) # path() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L25) ``` @type path() :: [String.t() | atom() | integer()] ``` [](Ash.Error.html#t:path_input/0) # path\_input() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L26) ``` @type path_input() :: [String.t() | atom() | integer()] | String.t() | atom() | integer() ``` [](Ash.Error.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L5) ``` @type t() :: %{ :__struct__ => module(), :__exception__ => true, :class => error_class(), :bread_crumbs => [String.t()], :vars => Keyword.t(), :stacktrace => Splode.Stacktrace.t() | nil, :context => map(), optional(atom()) => any() } ``` # [](Ash.Error.html#functions)Functions [](Ash.Error.html#ash_error?/1) # ash\_error?(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L159) ``` @spec ash_error?(term()) :: boolean() ``` Returns whether or not a term is an Ash.Error type. [](Ash.Error.html#error_descriptions/1) # error\_descriptions(errors) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L135) ``` @spec error_descriptions(term() | [term()]) :: String.t() ``` Converts errors into a single `String.t`. [](Ash.Error.html#set_path/2) # set\_path(errors, path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L167) ``` @spec set_path(ash_error() | [ash_error()], path_input()) :: ash_error() | [ash_error()] ``` ``` @spec set_path(ash_error_subject(), path_input()) :: ash_error_subject() ``` This function prepends the provided path to any existing path on the errors. [](Ash.Error.html#splode_error?/2) # splode\_error?(arg1, splode) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L5) [](Ash.Error.html#to_ash_error/3) # to\_ash\_error(value, stacktrace \\\\ nil, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L47) ``` @spec to_ash_error( error_input() | [error_input()], Exception.stacktrace() | nil, Keyword.t() ) :: ash_error() | [ash_error()] ``` Converts a value to an Ash exception. The supported inputs to this function can be provided to various places, like [`Ash.Query.add_error/2`](Ash.Query.html#add_error/2), [`Ash.Changeset.add_error/2`](Ash.Changeset.html#add_error/2) and [`Ash.ActionInput.add_error/2`](Ash.ActionInput.html#add_error/2). Additionally, any place that you can *return* an error you can return instead a valid error input. See [the error handling guide](error-handling.html) for more. [](Ash.Error.html#to_error_class/2) # to\_error\_class(value, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L72) ``` @spec to_error_class( ash_error_subject() | term() | [ash_error_subject()] | [term()], Keyword.t() ) :: t() ``` Converts a value to an Ash.Error type. [](Ash.Error.html#unwrap!/2) # unwrap!(result, opts \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/error.ex#L5) Raises an error if the result is an error, otherwise returns the result Alternatively, you can use the `defsplode` macro, which does this automatically. ### [](Ash.Error.html#unwrap!/2-options)Options - `:error_opts` - Options to pass to `to_error/2` when converting the returned error - `:unknown_error_opts` - Options to pass to the unknown error if the function returns only `:error`. not necessary if your function always returns `{:error, error}`. ### [](Ash.Error.html#unwrap!/2-examples)Examples def function(arg) do ``` case do_something(arg) do :success -> :ok {:success, result} -> {:ok, result} {:error, error} -> {:error, error} end ``` end def function!!(arg) do ``` YourErrors.unwrap!(function(arg)) ``` end [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.ActionRequiresPagination exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/action_requires_pagination.ex#L1 "View Source") Used when page option is passed but pagination is not enabled. # [](Ash.Error.Invalid.ActionRequiresPagination.html#summary)Summary ## [Functions](Ash.Error.Invalid.ActionRequiresPagination.html#functions) [exception()](Ash.Error.Invalid.ActionRequiresPagination.html#exception/0) # [](Ash.Error.Invalid.ActionRequiresPagination.html#functions)Functions [](Ash.Error.Invalid.ActionRequiresPagination.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/action_requires_pagination.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.AtomicsNotSupported exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/atomics_not_supported.ex#L1 "View Source") Used when atomics for the given action type are not not supported by the data layer, but one is used. # [](Ash.Error.Invalid.AtomicsNotSupported.html#summary)Summary ## [Functions](Ash.Error.Invalid.AtomicsNotSupported.html#functions) [exception()](Ash.Error.Invalid.AtomicsNotSupported.html#exception/0) # [](Ash.Error.Invalid.AtomicsNotSupported.html#functions)Functions [](Ash.Error.Invalid.AtomicsNotSupported.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/atomics_not_supported.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid.ex#L1 "View Source") The top level invalid error # [](Ash.Error.Invalid.html#summary)Summary ## [Types](Ash.Error.Invalid.html#types) [t()](Ash.Error.Invalid.html#t:t/0) ## [Functions](Ash.Error.Invalid.html#functions) [exception()](Ash.Error.Invalid.html#exception/0) [message(map)](Ash.Error.Invalid.html#message/1) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). # [](Ash.Error.Invalid.html#types)Types [](Ash.Error.Invalid.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid.ex#L5) ``` @type t() :: %Ash.Error.Invalid{ __exception__: true, action_input: Ash.ActionInput.t() | nil, bread_crumbs: term(), changeset: Ash.Changeset.t() | nil, class: term(), errors: term(), path: term(), query: Ash.Query.t() | nil, splode: term(), stacktrace: term(), vars: term() } ``` # [](Ash.Error.Invalid.html#functions)Functions [](Ash.Error.Invalid.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid.ex#L3) [](Ash.Error.Invalid.html#message/1) # message(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid.ex#L3) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.InvalidPrimaryKey exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/invalid_primary_key.ex#L1 "View Source") Used when an invalid primary key is given to [`Ash.get/2`](Ash.html#get/2) # [](Ash.Error.Invalid.InvalidPrimaryKey.html#summary)Summary ## [Functions](Ash.Error.Invalid.InvalidPrimaryKey.html#functions) [exception()](Ash.Error.Invalid.InvalidPrimaryKey.html#exception/0) # [](Ash.Error.Invalid.InvalidPrimaryKey.html#functions)Functions [](Ash.Error.Invalid.InvalidPrimaryKey.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/invalid_primary_key.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.LimitRequired exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/limit_required.ex#L1 "View Source") Used when no limit is provided, pagination is required, and no default page size is configured # [](Ash.Error.Invalid.LimitRequired.html#summary)Summary ## [Functions](Ash.Error.Invalid.LimitRequired.html#functions) [exception()](Ash.Error.Invalid.LimitRequired.html#exception/0) # [](Ash.Error.Invalid.LimitRequired.html#functions)Functions [](Ash.Error.Invalid.LimitRequired.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/limit_required.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.MultipleResults exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/multiple_results.ex#L1 "View Source") Used when multiple results are returned in a case where only one result was expected # [](Ash.Error.Invalid.MultipleResults.html#summary)Summary ## [Functions](Ash.Error.Invalid.MultipleResults.html#functions) [exception()](Ash.Error.Invalid.MultipleResults.html#exception/0) # [](Ash.Error.Invalid.MultipleResults.html#functions)Functions [](Ash.Error.Invalid.MultipleResults.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/multiple_results.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NoIdentityFound exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_identity_found.ex#L1 "View Source") Used when an identity name is used that does not reference identity on the resource # [](Ash.Error.Invalid.NoIdentityFound.html#summary)Summary ## [Functions](Ash.Error.Invalid.NoIdentityFound.html#functions) [exception()](Ash.Error.Invalid.NoIdentityFound.html#exception/0) # [](Ash.Error.Invalid.NoIdentityFound.html#functions)Functions [](Ash.Error.Invalid.NoIdentityFound.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_identity_found.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NoMatchingBulkStrategy exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_matching_bulk_strategy.ex#L1 "View Source") Used when an identity name is used that does not reference identity on the resource # [](Ash.Error.Invalid.NoMatchingBulkStrategy.html#summary)Summary ## [Functions](Ash.Error.Invalid.NoMatchingBulkStrategy.html#functions) [exception()](Ash.Error.Invalid.NoMatchingBulkStrategy.html#exception/0) # [](Ash.Error.Invalid.NoMatchingBulkStrategy.html#functions)Functions [](Ash.Error.Invalid.NoMatchingBulkStrategy.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_matching_bulk_strategy.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NonCountableAction exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/non_countable_action.ex#L1 "View Source") Used when page\[:count] option is passed but the action's pagination is not countable. # [](Ash.Error.Invalid.NonCountableAction.html#summary)Summary ## [Functions](Ash.Error.Invalid.NonCountableAction.html#functions) [exception()](Ash.Error.Invalid.NonCountableAction.html#exception/0) # [](Ash.Error.Invalid.NonCountableAction.html#functions)Functions [](Ash.Error.Invalid.NonCountableAction.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/non_countable_action.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NonStreamableAction exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/non_streamable_action.ex#L1 "View Source") Used when Ash.stream is used with an action that does not support keyset pagination # [](Ash.Error.Invalid.NonStreamableAction.html#summary)Summary ## [Functions](Ash.Error.Invalid.NonStreamableAction.html#functions) [exception()](Ash.Error.Invalid.NonStreamableAction.html#exception/0) # [](Ash.Error.Invalid.NonStreamableAction.html#functions)Functions [](Ash.Error.Invalid.NonStreamableAction.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/non_streamable_action.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NoPrimaryAction exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_primary_action.ex#L1 "View Source") Used when an action name is provided that doesn't exist # [](Ash.Error.Invalid.NoPrimaryAction.html#summary)Summary ## [Functions](Ash.Error.Invalid.NoPrimaryAction.html#functions) [exception()](Ash.Error.Invalid.NoPrimaryAction.html#exception/0) # [](Ash.Error.Invalid.NoPrimaryAction.html#functions)Functions [](Ash.Error.Invalid.NoPrimaryAction.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_primary_action.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NoSuchAction exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_such_action.ex#L1 "View Source") Used when an action name is provided that doesn't exist # [](Ash.Error.Invalid.NoSuchAction.html#summary)Summary ## [Functions](Ash.Error.Invalid.NoSuchAction.html#functions) [exception()](Ash.Error.Invalid.NoSuchAction.html#exception/0) # [](Ash.Error.Invalid.NoSuchAction.html#functions)Functions [](Ash.Error.Invalid.NoSuchAction.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_such_action.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NoSuchInput exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_such_input.ex#L1 "View Source") Used when an input is provided to an action or calculation that is not accepted # [](Ash.Error.Invalid.NoSuchInput.html#summary)Summary ## [Functions](Ash.Error.Invalid.NoSuchInput.html#functions) [exception()](Ash.Error.Invalid.NoSuchInput.html#exception/0) # [](Ash.Error.Invalid.NoSuchInput.html#functions)Functions [](Ash.Error.Invalid.NoSuchInput.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_such_input.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.NoSuchResource exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_such_resource.ex#L1 "View Source") Used when a resource or alias is provided that doesn't exist # [](Ash.Error.Invalid.NoSuchResource.html#summary)Summary ## [Functions](Ash.Error.Invalid.NoSuchResource.html#functions) [exception()](Ash.Error.Invalid.NoSuchResource.html#exception/0) # [](Ash.Error.Invalid.NoSuchResource.html#functions)Functions [](Ash.Error.Invalid.NoSuchResource.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/no_such_resource.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.PaginationRequired exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/pagination_required.ex#L1 "View Source") Used when `page: false` is provided but pagination is required # [](Ash.Error.Invalid.PaginationRequired.html#summary)Summary ## [Functions](Ash.Error.Invalid.PaginationRequired.html#functions) [exception()](Ash.Error.Invalid.PaginationRequired.html#exception/0) # [](Ash.Error.Invalid.PaginationRequired.html#functions)Functions [](Ash.Error.Invalid.PaginationRequired.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/pagination_required.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.ResourceNotAllowed exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/resource_not_allowed.ex#L1 "View Source") Used when a resource or alias is provided that cannot be used with the given domain # [](Ash.Error.Invalid.ResourceNotAllowed.html#summary)Summary ## [Functions](Ash.Error.Invalid.ResourceNotAllowed.html#functions) [exception()](Ash.Error.Invalid.ResourceNotAllowed.html#exception/0) # [](Ash.Error.Invalid.ResourceNotAllowed.html#functions)Functions [](Ash.Error.Invalid.ResourceNotAllowed.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/resource_not_allowed.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.TenantRequired exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/tenant_required.ex#L1 "View Source") Used when a tenant is not specified # [](Ash.Error.Invalid.TenantRequired.html#summary)Summary ## [Functions](Ash.Error.Invalid.TenantRequired.html#functions) [exception()](Ash.Error.Invalid.TenantRequired.html#exception/0) # [](Ash.Error.Invalid.TenantRequired.html#functions)Functions [](Ash.Error.Invalid.TenantRequired.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/tenant_required.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.Timeout exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/timeout.ex#L1 "View Source") Used when a request to a domain times out. # [](Ash.Error.Invalid.Timeout.html#summary)Summary ## [Functions](Ash.Error.Invalid.Timeout.html#functions) [exception()](Ash.Error.Invalid.Timeout.html#exception/0) # [](Ash.Error.Invalid.Timeout.html#functions)Functions [](Ash.Error.Invalid.Timeout.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/timeout.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.TimeoutNotSupported exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/timeout_not_supported.ex#L1 "View Source") Used when timeouts are not supported by the data layer, but one is set # [](Ash.Error.Invalid.TimeoutNotSupported.html#summary)Summary ## [Functions](Ash.Error.Invalid.TimeoutNotSupported.html#functions) [exception()](Ash.Error.Invalid.TimeoutNotSupported.html#exception/0) # [](Ash.Error.Invalid.TimeoutNotSupported.html#functions)Functions [](Ash.Error.Invalid.TimeoutNotSupported.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/timeout_not_supported.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Invalid.Unavailable exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/unavailable.ex#L1 "View Source") Used when a given resource is unavailable. This might happen due to locking at the data layer, or something you implement yourself. # [](Ash.Error.Invalid.Unavailable.html#summary)Summary ## [Functions](Ash.Error.Invalid.Unavailable.html#functions) [exception()](Ash.Error.Invalid.Unavailable.html#exception/0) # [](Ash.Error.Invalid.Unavailable.html#functions)Functions [](Ash.Error.Invalid.Unavailable.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/invalid/unavailable.ex#L10) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Load.InvalidQuery exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/load/invalid_query.ex#L1 "View Source") Used when an invalid query is provided in a load # [](Ash.Error.Load.InvalidQuery.html#summary)Summary ## [Functions](Ash.Error.Load.InvalidQuery.html#functions) [exception()](Ash.Error.Load.InvalidQuery.html#exception/0) # [](Ash.Error.Load.InvalidQuery.html#functions)Functions [](Ash.Error.Load.InvalidQuery.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/load/invalid_query.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Load.NoSuchRelationship exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/load/no_such_relationship.ex#L1 "View Source") Used when attempting to load a relationship that does not exist # [](Ash.Error.Load.NoSuchRelationship.html#summary)Summary ## [Functions](Ash.Error.Load.NoSuchRelationship.html#functions) [exception()](Ash.Error.Load.NoSuchRelationship.html#exception/0) # [](Ash.Error.Load.NoSuchRelationship.html#functions)Functions [](Ash.Error.Load.NoSuchRelationship.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/load/no_such_relationship.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Page.InvalidKeyset exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/page/invalid_keyset.ex#L1 "View Source") Used when a value is provided for a keyset that cannot be Base64 decoded. # [](Ash.Error.Page.InvalidKeyset.html#summary)Summary ## [Functions](Ash.Error.Page.InvalidKeyset.html#functions) [exception()](Ash.Error.Page.InvalidKeyset.html#exception/0) # [](Ash.Error.Page.InvalidKeyset.html#functions)Functions [](Ash.Error.Page.InvalidKeyset.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/page/invalid_keyset.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.AggregatesNotSupported exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/aggregates_not_supported.ex#L1 "View Source") Used when the data\_layer does not support aggregates, or filtering/sorting them # [](Ash.Error.Query.AggregatesNotSupported.html#summary)Summary ## [Functions](Ash.Error.Query.AggregatesNotSupported.html#functions) [exception()](Ash.Error.Query.AggregatesNotSupported.html#exception/0) # [](Ash.Error.Query.AggregatesNotSupported.html#functions)Functions [](Ash.Error.Query.AggregatesNotSupported.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/aggregates_not_supported.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.CalculationRequiresPrimaryKey exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/calculation_requires_primary_key.ex#L1 "View Source") Used when a calculation requires a primary key but was not supplied with one # [](Ash.Error.Query.CalculationRequiresPrimaryKey.html#summary)Summary ## [Functions](Ash.Error.Query.CalculationRequiresPrimaryKey.html#functions) [exception()](Ash.Error.Query.CalculationRequiresPrimaryKey.html#exception/0) # [](Ash.Error.Query.CalculationRequiresPrimaryKey.html#functions)Functions [](Ash.Error.Query.CalculationRequiresPrimaryKey.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/calculation_requires_primary_key.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.CalculationsNotSupported exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/calculations_not_supported.ex#L1 "View Source") Used when the data\_layer does not support calculations, or filtering/sorting them # [](Ash.Error.Query.CalculationsNotSupported.html#summary)Summary ## [Functions](Ash.Error.Query.CalculationsNotSupported.html#functions) [exception()](Ash.Error.Query.CalculationsNotSupported.html#exception/0) # [](Ash.Error.Query.CalculationsNotSupported.html#functions)Functions [](Ash.Error.Query.CalculationsNotSupported.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/calculations_not_supported.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidArgument exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_argument.ex#L1 "View Source") Used when an invalid value is provided for an action argument # [](Ash.Error.Query.InvalidArgument.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidArgument.html#functions) [exception()](Ash.Error.Query.InvalidArgument.html#exception/0) # [](Ash.Error.Query.InvalidArgument.html#functions)Functions [](Ash.Error.Query.InvalidArgument.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_argument.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidCalculationArgument exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_calculation_argument.ex#L1 "View Source") Used when an invalid value is provided for a calculation argument # [](Ash.Error.Query.InvalidCalculationArgument.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidCalculationArgument.html#functions) [exception()](Ash.Error.Query.InvalidCalculationArgument.html#exception/0) # [](Ash.Error.Query.InvalidCalculationArgument.html#functions)Functions [](Ash.Error.Query.InvalidCalculationArgument.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_calculation_argument.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidExpression exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_expression.ex#L1 "View Source") Used when an invalid expression is used in a filter # [](Ash.Error.Query.InvalidExpression.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidExpression.html#functions) [exception()](Ash.Error.Query.InvalidExpression.html#exception/0) # [](Ash.Error.Query.InvalidExpression.html#functions)Functions [](Ash.Error.Query.InvalidExpression.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_expression.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidFilterReference exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_filter_reference.ex#L1 "View Source") Used when an invalid reference is used in a filter # [](Ash.Error.Query.InvalidFilterReference.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidFilterReference.html#functions) [exception()](Ash.Error.Query.InvalidFilterReference.html#exception/0) # [](Ash.Error.Query.InvalidFilterReference.html#functions)Functions [](Ash.Error.Query.InvalidFilterReference.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_filter_reference.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidFilterValue exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_filter_value.ex#L1 "View Source") Used when an invalid value is provided for a filter # [](Ash.Error.Query.InvalidFilterValue.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidFilterValue.html#functions) [exception()](Ash.Error.Query.InvalidFilterValue.html#exception/0) # [](Ash.Error.Query.InvalidFilterValue.html#functions)Functions [](Ash.Error.Query.InvalidFilterValue.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_filter_value.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidLimit exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_limit.ex#L1 "View Source") Used when an invalid limit is provided # [](Ash.Error.Query.InvalidLimit.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidLimit.html#functions) [exception()](Ash.Error.Query.InvalidLimit.html#exception/0) # [](Ash.Error.Query.InvalidLimit.html#functions)Functions [](Ash.Error.Query.InvalidLimit.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_limit.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidLoad exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_load.ex#L1 "View Source") Used when an invalid load is provided # [](Ash.Error.Query.InvalidLoad.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidLoad.html#functions) [exception()](Ash.Error.Query.InvalidLoad.html#exception/0) # [](Ash.Error.Query.InvalidLoad.html#functions)Functions [](Ash.Error.Query.InvalidLoad.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_load.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidOffset exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_offset.ex#L1 "View Source") Used when an invalid offset is provided # [](Ash.Error.Query.InvalidOffset.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidOffset.html#functions) [exception()](Ash.Error.Query.InvalidOffset.html#exception/0) # [](Ash.Error.Query.InvalidOffset.html#functions)Functions [](Ash.Error.Query.InvalidOffset.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_offset.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidPage exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_page.ex#L1 "View Source") Used when an invalid page option is provided # [](Ash.Error.Query.InvalidPage.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidPage.html#functions) [exception()](Ash.Error.Query.InvalidPage.html#exception/0) # [](Ash.Error.Query.InvalidPage.html#functions)Functions [](Ash.Error.Query.InvalidPage.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_page.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidQuery exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_query.ex#L1 "View Source") A generic error that can be used to add an error to a query for a specific field # [](Ash.Error.Query.InvalidQuery.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidQuery.html#functions) [exception()](Ash.Error.Query.InvalidQuery.html#exception/0) # [](Ash.Error.Query.InvalidQuery.html#functions)Functions [](Ash.Error.Query.InvalidQuery.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_query.ex#L7) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.InvalidSortOrder exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_sort_order.ex#L1 "View Source") Used when an invalid sort order is provided # [](Ash.Error.Query.InvalidSortOrder.html#summary)Summary ## [Functions](Ash.Error.Query.InvalidSortOrder.html#functions) [exception()](Ash.Error.Query.InvalidSortOrder.html#exception/0) # [](Ash.Error.Query.InvalidSortOrder.html#functions)Functions [](Ash.Error.Query.InvalidSortOrder.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/invalid_sort_order.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.LockNotSupported exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/lock_not_supported.ex#L1 "View Source") Used when the data\_layer does not support a given lock type # [](Ash.Error.Query.LockNotSupported.html#summary)Summary ## [Functions](Ash.Error.Query.LockNotSupported.html#functions) [exception()](Ash.Error.Query.LockNotSupported.html#exception/0) # [](Ash.Error.Query.LockNotSupported.html#functions)Functions [](Ash.Error.Query.LockNotSupported.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/lock_not_supported.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoComplexSortsWithKeysetPagination exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_complex_sorts_with_keyset_pagination.ex#L1 "View Source") Due to the filter-based implementation of keyset pagination, it cannot be used with sorts on calculations. We could solve this problem by making the keyset only be the primary key of the record, and then fetching that value loading the calculations/aggregates that we need. If we do this we should either: 1.) make it a new pagination mode or 2.) add an option like `mode: :strict | :fetch` to pagination options. Let me know if you're reading this and want to help implement it. # [](Ash.Error.Query.NoComplexSortsWithKeysetPagination.html#summary)Summary ## [Functions](Ash.Error.Query.NoComplexSortsWithKeysetPagination.html#functions) [exception()](Ash.Error.Query.NoComplexSortsWithKeysetPagination.html#exception/0) # [](Ash.Error.Query.NoComplexSortsWithKeysetPagination.html#functions)Functions [](Ash.Error.Query.NoComplexSortsWithKeysetPagination.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_complex_sorts_with_keyset_pagination.ex#L14) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoReadAction exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_read_action.ex#L1 "View Source") Used when a resource would be read but has no read action # [](Ash.Error.Query.NoReadAction.html#summary)Summary ## [Functions](Ash.Error.Query.NoReadAction.html#functions) [exception()](Ash.Error.Query.NoReadAction.html#exception/0) # [](Ash.Error.Query.NoReadAction.html#functions)Functions [](Ash.Error.Query.NoReadAction.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_read_action.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoSuchAttribute exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_attribute.ex#L1 "View Source") Used when an attribute that doesn't exist is used in a query # [](Ash.Error.Query.NoSuchAttribute.html#summary)Summary ## [Functions](Ash.Error.Query.NoSuchAttribute.html#functions) [exception()](Ash.Error.Query.NoSuchAttribute.html#exception/0) # [](Ash.Error.Query.NoSuchAttribute.html#functions)Functions [](Ash.Error.Query.NoSuchAttribute.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_attribute.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoSuchField exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_field.ex#L1 "View Source") Used when a field(attrbute, calculation, aggregate or relationship) that doesn't exist is used in a query # [](Ash.Error.Query.NoSuchField.html#summary)Summary ## [Functions](Ash.Error.Query.NoSuchField.html#functions) [exception()](Ash.Error.Query.NoSuchField.html#exception/0) # [](Ash.Error.Query.NoSuchField.html#functions)Functions [](Ash.Error.Query.NoSuchField.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_field.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoSuchFilterPredicate exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_filter_predicate.ex#L1 "View Source") Used when a filter predicate that does not exist is referenced # [](Ash.Error.Query.NoSuchFilterPredicate.html#summary)Summary ## [Functions](Ash.Error.Query.NoSuchFilterPredicate.html#functions) [exception()](Ash.Error.Query.NoSuchFilterPredicate.html#exception/0) # [](Ash.Error.Query.NoSuchFilterPredicate.html#functions)Functions [](Ash.Error.Query.NoSuchFilterPredicate.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_filter_predicate.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoSuchFunction exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_function.ex#L1 "View Source") Used when an function that doesn't exist is used in a query # [](Ash.Error.Query.NoSuchFunction.html#summary)Summary ## [Functions](Ash.Error.Query.NoSuchFunction.html#functions) [exception()](Ash.Error.Query.NoSuchFunction.html#exception/0) # [](Ash.Error.Query.NoSuchFunction.html#functions)Functions [](Ash.Error.Query.NoSuchFunction.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_function.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoSuchOperator exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_operator.ex#L1 "View Source") Used when an operator that doesn't exist is used in a query # [](Ash.Error.Query.NoSuchOperator.html#summary)Summary ## [Functions](Ash.Error.Query.NoSuchOperator.html#functions) [exception()](Ash.Error.Query.NoSuchOperator.html#exception/0) # [](Ash.Error.Query.NoSuchOperator.html#functions)Functions [](Ash.Error.Query.NoSuchOperator.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_operator.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NoSuchRelationship exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_relationship.ex#L1 "View Source") Used when an relationship that doesn't exist is used in a query # [](Ash.Error.Query.NoSuchRelationship.html#summary)Summary ## [Functions](Ash.Error.Query.NoSuchRelationship.html#functions) [exception()](Ash.Error.Query.NoSuchRelationship.html#exception/0) # [](Ash.Error.Query.NoSuchRelationship.html#functions)Functions [](Ash.Error.Query.NoSuchRelationship.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/no_such_relationship.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.NotFound exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/not_found.ex#L1 "View Source") Used when an entity that not exist is referenced # [](Ash.Error.Query.NotFound.html#summary)Summary ## [Functions](Ash.Error.Query.NotFound.html#functions) [exception()](Ash.Error.Query.NotFound.html#exception/0) # [](Ash.Error.Query.NotFound.html#functions)Functions [](Ash.Error.Query.NotFound.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/not_found.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.ReadActionRequired exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/read_action_required.ex#L1 "View Source") Used when a relationship is filtered and the destination does not have a default read action # [](Ash.Error.Query.ReadActionRequired.html#summary)Summary ## [Functions](Ash.Error.Query.ReadActionRequired.html#functions) [exception()](Ash.Error.Query.ReadActionRequired.html#exception/0) # [](Ash.Error.Query.ReadActionRequired.html#functions)Functions [](Ash.Error.Query.ReadActionRequired.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/read_action_required.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.ReadActionRequiresActor exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/read_action_requires_actor.ex#L1 "View Source") Used when an actor is referenced in a filter template, but no actor exists # [](Ash.Error.Query.ReadActionRequiresActor.html#summary)Summary ## [Functions](Ash.Error.Query.ReadActionRequiresActor.html#functions) [exception()](Ash.Error.Query.ReadActionRequiresActor.html#exception/0) # [](Ash.Error.Query.ReadActionRequiresActor.html#functions)Functions [](Ash.Error.Query.ReadActionRequiresActor.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/read_action_requires_actor.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.Required exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/required.ex#L1 "View Source") Used when a filter or argument is required in a query # [](Ash.Error.Query.Required.html#summary)Summary ## [Functions](Ash.Error.Query.Required.html#functions) [exception()](Ash.Error.Query.Required.html#exception/0) # [](Ash.Error.Query.Required.html#functions)Functions [](Ash.Error.Query.Required.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/required.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.UnsortableField exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/unsortable_field.ex#L1 "View Source") Used when attempting to sort on a field that cannot be used for sorting # [](Ash.Error.Query.UnsortableField.html#summary)Summary ## [Functions](Ash.Error.Query.UnsortableField.html#functions) [exception()](Ash.Error.Query.UnsortableField.html#exception/0) # [](Ash.Error.Query.UnsortableField.html#functions)Functions [](Ash.Error.Query.UnsortableField.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/unsortable_field.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Query.UnsupportedPredicate exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/unsupported_predicate.ex#L1 "View Source") Used when the data\_layer does not support a provided predicate # [](Ash.Error.Query.UnsupportedPredicate.html#summary)Summary ## [Functions](Ash.Error.Query.UnsupportedPredicate.html#functions) [exception()](Ash.Error.Query.UnsupportedPredicate.html#exception/0) # [](Ash.Error.Query.UnsupportedPredicate.html#functions)Functions [](Ash.Error.Query.UnsupportedPredicate.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/query/unsupported_predicate.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.SimpleDataLayer.NoDataProvided exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/simple_data_layer/no_data_provided.ex#L1 "View Source") Used when no data was provided to the simple data layer # [](Ash.Error.SimpleDataLayer.NoDataProvided.html#summary)Summary ## [Functions](Ash.Error.SimpleDataLayer.NoDataProvided.html#functions) [exception()](Ash.Error.SimpleDataLayer.NoDataProvided.html#exception/0) # [](Ash.Error.SimpleDataLayer.NoDataProvided.html#functions)Functions [](Ash.Error.SimpleDataLayer.NoDataProvided.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/simple_data_layer/no_data_provided.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Stacktrace (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/stacktrace.ex#L1 "View Source") A placeholder for a stacktrace so that we can avoid printing it everywhere # [](Ash.Error.Stacktrace.html#summary)Summary ## [Types](Ash.Error.Stacktrace.html#types) [t()](Ash.Error.Stacktrace.html#t:t/0) # [](Ash.Error.Stacktrace.html#types)Types [](Ash.Error.Stacktrace.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/stacktrace.ex#L5) ``` @type t() :: %Ash.Error.Stacktrace{stacktrace: list()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Unknown exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown.ex#L1 "View Source") The top level unknown error container # [](Ash.Error.Unknown.html#summary)Summary ## [Types](Ash.Error.Unknown.html#types) [t()](Ash.Error.Unknown.html#t:t/0) ## [Functions](Ash.Error.Unknown.html#functions) [exception()](Ash.Error.Unknown.html#exception/0) [exception(args)](Ash.Error.Unknown.html#exception/1) Construction an exception using the arguments passed in. You can see Elixir's doc on [`Exception/1`](../elixir/Kernel.SpecialForms.html#__aliases__/1) for more information. [message(map)](Ash.Error.Unknown.html#message/1) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). # [](Ash.Error.Unknown.html#types)Types [](Ash.Error.Unknown.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown.ex#L5) ``` @type t() :: %Ash.Error.Unknown{ __exception__: true, action_input: Ash.ActionInput.t() | nil, bread_crumbs: term(), changeset: Ash.Changeset.t() | nil, class: term(), errors: term(), path: term(), query: Ash.Query.t() | nil, splode: term(), stacktrace: term(), vars: term() } ``` # [](Ash.Error.Unknown.html#functions)Functions [](Ash.Error.Unknown.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown.ex#L3) [](Ash.Error.Unknown.html#exception/1) # exception(args) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown.ex#L17) ``` @spec exception(Keyword.t()) :: t() ``` Construction an exception using the arguments passed in. You can see Elixir's doc on [`Exception/1`](../elixir/Kernel.SpecialForms.html#__aliases__/1) for more information. [](Ash.Error.Unknown.html#message/1) # message(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown.ex#L3) Callback implementation for [`Exception.message/1`](../elixir/Exception.html#c:message/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Error.Unknown.UnknownError exception (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown/unknown_error.ex#L1 "View Source") Used when an unknown error occurs # [](Ash.Error.Unknown.UnknownError.html#summary)Summary ## [Types](Ash.Error.Unknown.UnknownError.html#types) [t()](Ash.Error.Unknown.UnknownError.html#t:t/0) ## [Functions](Ash.Error.Unknown.UnknownError.html#functions) [exception()](Ash.Error.Unknown.UnknownError.html#exception/0) # [](Ash.Error.Unknown.UnknownError.html#types)Types [](Ash.Error.Unknown.UnknownError.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown/unknown_error.ex#L7) ``` @type t() :: %Ash.Error.Unknown.UnknownError{ __exception__: true, bread_crumbs: term(), class: term(), error: binary() | nil, field: term() | nil, path: term(), splode: term(), stacktrace: term(), value: term() | nil, vars: term() } ``` # [](Ash.Error.Unknown.UnknownError.html#functions)Functions [](Ash.Error.Unknown.UnknownError.html#exception/0) # exception() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/error/unknown/unknown_error.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Expr (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L1 "View Source") Tools to build Ash expressions # [](Ash.Expr.html#summary)Summary ## [Types](Ash.Expr.html#types) [t()](Ash.Expr.html#t:t/0) ## [Functions](Ash.Expr.html#functions) [actor(value)](Ash.Expr.html#actor/1) A template helper for using actor values in filter templates [arg(name)](Ash.Expr.html#arg/1) A template helper for using action arguments in filter templates [atomic\_ref(expr)](Ash.Expr.html#atomic_ref/1) A template helper for referring to the most recent atomic expression applied to an update field [can\_return\_nil?(pred)](Ash.Expr.html#can_return_nil?/1) [context(name)](Ash.Expr.html#context/1) A template helper for using query context in filter templates [determine\_type(value)](Ash.Expr.html#determine_type/1) [determine\_types(mod, args, returns \\\\ nil, nested? \\\\ false)](Ash.Expr.html#determine_types/4) [eval(expression, opts \\\\ \[\])](Ash.Expr.html#eval/2) Evaluate an expression. This function only works if you have no references, or if you provide the `record` option. [eval!(expression, opts \\\\ \[\])](Ash.Expr.html#eval!/2) Evaluate an expression. See [`eval/2`](Ash.Expr.html#eval/2) for more. [expr(body)](Ash.Expr.html#expr/1) [expr?(value)](Ash.Expr.html#expr?/1) Returns true if the value is or contains an expression [or\_where(left, right)](Ash.Expr.html#or_where/2) [parent(expr)](Ash.Expr.html#parent/1) A template helper for creating a parent reference [ref(name)](Ash.Expr.html#ref/1) A template helper for creating a reference [ref(path, name)](Ash.Expr.html#ref/2) A template helper for creating a reference to a related path [template\_references?(list, pred)](Ash.Expr.html#template_references?/2) Whether or not a given template contains an actor reference [template\_references\_argument?(template)](Ash.Expr.html#template_references_argument?/1) [template\_references\_context?(template)](Ash.Expr.html#template_references_context?/1) [where(left, right)](Ash.Expr.html#where/2) # [](Ash.Expr.html#types)Types [](Ash.Expr.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L5) ``` @type t() :: any() ``` # [](Ash.Expr.html#functions)Functions [](Ash.Expr.html#actor/1) # actor(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L84) A template helper for using actor values in filter templates [](Ash.Expr.html#arg/1) # arg(name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L87) A template helper for using action arguments in filter templates [](Ash.Expr.html#atomic_ref/1) # atomic\_ref(expr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L99) A template helper for referring to the most recent atomic expression applied to an update field [](Ash.Expr.html#can_return_nil?/1) # can\_return\_nil?(pred) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L245) [](Ash.Expr.html#context/1) # context(name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L106) A template helper for using query context in filter templates An atom will get the value for a key, and a list will be accessed via `get_in`. [](Ash.Expr.html#determine_type/1) # determine\_type(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L1273) [](Ash.Expr.html#determine_types/4) # determine\_types(mod, args, returns \\\\ nil, nested? \\\\ false) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L880) [](Ash.Expr.html#eval/2) # eval(expression, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L24) Evaluate an expression. This function only works if you have no references, or if you provide the `record` option. [](Ash.Expr.html#eval!/2) # eval!(expression, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L11) Evaluate an expression. See [`eval/2`](Ash.Expr.html#eval/2) for more. [](Ash.Expr.html#expr/1) # expr(body) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L145) ``` @spec expr(Macro.t()) :: t() ``` [](Ash.Expr.html#expr?/1) # expr?(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L44) ``` @spec expr?(term()) :: boolean() ``` Returns true if the value is or contains an expression [](Ash.Expr.html#or_where/2) # or\_where(left, right) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L134) ``` @spec or_where(Macro.t(), Macro.t()) :: t() ``` [](Ash.Expr.html#parent/1) # parent(expr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L96) A template helper for creating a parent reference [](Ash.Expr.html#ref/1) # ref(name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L90) A template helper for creating a reference [](Ash.Expr.html#ref/2) # ref(path, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L93) A template helper for creating a reference to a related path [](Ash.Expr.html#template_references?/2) # template\_references?(list, pred) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L278) Whether or not a given template contains an actor reference [](Ash.Expr.html#template_references_argument?/1) # template\_references\_argument?(template) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L231) [](Ash.Expr.html#template_references_context?/1) # template\_references\_context?(template) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L238) [](Ash.Expr.html#where/2) # where(left, right) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/expr/expr.ex#L123) ``` @spec where(Macro.t(), Macro.t()) :: t() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Extension behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L1 "View Source") A behavior of additional callbacks that extensions can implement, specific to Ash. It is not necessary to adopt this behavior, but it is recommended to do so if you want to define these functions on your extension. These functions are invoked when their relevant Mix task is run. # [](Ash.Extension.html#summary)Summary ## [Types](Ash.Extension.html#types) [argv()](Ash.Extension.html#t:argv/0) [igniter()](Ash.Extension.html#t:igniter/0) ## [Callbacks](Ash.Extension.html#callbacks) [codegen(argv)](Ash.Extension.html#c:codegen/1) [install(igniter, module, type, location, argv)](Ash.Extension.html#c:install/5) [migrate(argv)](Ash.Extension.html#c:migrate/1) [reset(argv)](Ash.Extension.html#c:reset/1) [rollback(argv)](Ash.Extension.html#c:rollback/1) [setup argv](Ash.Extension.html#c:setup/1) [tear\_down(argv)](Ash.Extension.html#c:tear_down/1) # [](Ash.Extension.html#types)Types [](Ash.Extension.html#t:argv/0) # argv() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L9) ``` @type argv() :: [String.t()] ``` [](Ash.Extension.html#t:igniter/0) # igniter() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L12) ``` @type igniter() :: Igniter.t() ``` # [](Ash.Extension.html#callbacks)Callbacks [](Ash.Extension.html#c:codegen/1) # codegen(argv) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L22) ``` @callback codegen(argv()) :: term() ``` [](Ash.Extension.html#c:install/5) # install(igniter, module, type, location, argv) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L24) ``` @callback install( igniter(), module :: module(), type :: Ash.Resource.t() | Ash.Domain.t(), location :: String.t(), argv() ) :: igniter() ``` [](Ash.Extension.html#c:migrate/1) # migrate(argv) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L17) ``` @callback migrate(argv()) :: term() ``` [](Ash.Extension.html#c:reset/1) # reset(argv) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L18) ``` @callback reset(argv()) :: term() ``` [](Ash.Extension.html#c:rollback/1) # rollback(argv) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L19) ``` @callback rollback(argv()) :: term() ``` [](Ash.Extension.html#c:setup/1) # setup argv (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L20) ``` @callback setup(argv()) :: term() ``` [](Ash.Extension.html#c:tear_down/1) # tear\_down(argv) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/extension.ex#L21) ``` @callback tear_down(argv()) :: term() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Filter (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L1 "View Source") The representation of a filter in Ash. ## [](Ash.Filter.html#module-security-concerns)Security Concerns Do not pass user input directly to [`Ash.Query.filter/2`](Ash.Query.html#filter/2), it will not be sanitised. Instead use [`Ash.Filter.parse_input/2`](Ash.Filter.html#parse_input/2) or [`Ash.Query.filter_input/2`](Ash.Query.html#filter_input/2). Refer to those functions for more information on how to safely work with user input. ## [](Ash.Filter.html#module-writing-a-filter)Writing a filter ### [](Ash.Filter.html#module-built-in-predicates)Built In Predicates - `is_nil` - `==` - `!=` - `in` - `<` - `>` - `<=` - `>=` - `&&` - `||` - `<>` - `/` - `-` - `*` - `+` - `equals` (alias for `==`) - `not_equals` (alias for `!=`) - `gt` (alias for `>`) - `lt` (alias for `<`) - `gte` (alias for `>=`) - `lte` (alias for `<=`) - `eq` (alias for `==`) - `not_eq` (alias for `!=`) - `less_than` (alias for `<`) - `greater_than` (alias for `>`) - `less_than_or_equal` (alias for `<=`) - `greater_than_or_equal` (alias for `>=`) - `and` (alias for `&&`) - `or` (alias for `||`) - `concat` (alias for `<>`) - `div` (alias for `/`) - `minus` (alias for `-`) - `times` (alias for `*`) - `plus` (alias for `+`) ### [](Ash.Filter.html#module-booleanexpression-syntax)BooleanExpression syntax The expression syntax ultimately just builds the keyword list style filter, but with lots of conveniences that would be very annoying to do manually. Examples ``` Ash.Query.filter(resource, name == "Zardoz") Ash.Query.filter(resource, first_name == "Zar" and last_name == "Doz") Ash.Query.filter(resource, first_name == "Zar" and last_name in ["Doz", "Daz"] and high_score > 10) Ash.Query.filter(resource, first_name == "Zar" or last_name == "Doz" or (high_score > 10 and high_score < -10)) ``` ### [](Ash.Filter.html#module-expressions)Expressions More complex filters can be built using Ash Expressions. Examples ``` # Filter based on the contents of a string attribute Ash.Query.filter(Helpdesk.Support.Ticket, contains(subject, "2")) # Filter based on the attribute of a joined relationship: Ash.Query.filter(Helpdesk.Support.Ticket, representative.name == ^name) ``` See the [Expressions guide](expressions.html) guide for more information. ### [](Ash.Filter.html#module-keyword-list-syntax)Keyword list syntax A filter is a nested keyword list (with some exceptions, like `true` for everything and `false` for nothing). The key is the "predicate" (or "condition") and the value is the parameter. You can use `and` and `or` to create nested filters. Data layers can expose custom predicates. Eventually, you will be able to define your own custom predicates, which will be a mechanism for you to attach complex filters supported by the data layer to your queries. **Important** In a given keyword list, all predicates are considered to be "ands". So `[or: [first_name: "Tom", last_name: "Bombadil"]]` doesn't mean 'First name == "tom" or last\_name == "bombadil"'. To say that, you want to provide a list of filters, like so: `[or: [[first_name: "Tom"], [last_name: "Bombadil"]]]` Some example filters: ``` Ash.Query.filter(resource, [name: "Zardoz"]) Ash.Query.filter(resource, [first_name: "Zar", last_name: "Doz"]) Ash.Query.filter(resource, [first_name: "Zar", last_name: [in: ["Doz", "Daz"]], high_score: [greater_than: 10]]) Ash.Query.filter(resource, [or: [ [first_name: "Zar"], [last_name: "Doz"], [or: [ [high_score: [greater_than: 10]]], [high_score: [less_than: -10]] ] ]]) ``` ### [](Ash.Filter.html#module-other-formats)Other formats Maps are also accepted, as are maps with string keys. Technically, a list of `[{"string_key", value}]` would also work. # [](Ash.Filter.html#summary)Summary ## [Types](Ash.Filter.html#types) [t()](Ash.Filter.html#t:t/0) ## [Functions](Ash.Filter.html#functions) [add\_to\_filter(base, addition, op \\\\ :and, aggregates \\\\ %{}, calculations \\\\ %{}, context \\\\ %{})](Ash.Filter.html#add_to_filter/6) [add\_to\_filter!(base, addition, op \\\\ :and, aggregates \\\\ %{}, calculations \\\\ %{}, context \\\\ %{})](Ash.Filter.html#add_to_filter!/6) [builtin\_functions()](Ash.Filter.html#builtin_functions/0) [builtin\_operators()](Ash.Filter.html#builtin_operators/0) [builtin\_predicate\_operators()](Ash.Filter.html#builtin_predicate_operators/0) [builtins()](Ash.Filter.html#builtins/0) [custom\_expression(name, args)](Ash.Filter.html#custom_expression/2) [do\_hydrate\_refs(filter, context)](Ash.Filter.html#do_hydrate_refs/2) [fetch\_simple\_equality\_predicate(expression, attribute)](Ash.Filter.html#fetch_simple_equality_predicate/2) Can be used to find a simple equality predicate on an attribute [find(expr, pred, ors? \\\\ true, ands? \\\\ true)](Ash.Filter.html#find/4) Find an expression inside of a filter that matches the provided predicate [find\_simple\_equality\_predicate(expression, attribute)](Ash.Filter.html#find_simple_equality_predicate/2) Can be used to find a simple equality predicate on an attribute [find\_value(expr, pred)](Ash.Filter.html#find_value/2) [flat\_map(expression, func)](Ash.Filter.html#flat_map/2) [get\_filter(resource, id)](Ash.Filter.html#get_filter/2) Returns a filter statement that would find a single record based on the input. [get\_function(key, resource, public?)](Ash.Filter.html#get_function/3) [get\_operator(key)](Ash.Filter.html#get_operator/1) [get\_predicate\_function(key, resource, public?)](Ash.Filter.html#get_predicate_function/3) [hydrate\_refs(value, context)](Ash.Filter.html#hydrate_refs/2) [list\_predicates(expression)](Ash.Filter.html#list_predicates/1) [list\_refs(expression, no\_longer\_simple? \\\\ false, in\_an\_eq? \\\\ false, expand\_calculations? \\\\ false, expand\_get\_path? \\\\ false)](Ash.Filter.html#list_refs/5) [map(filter, func)](Ash.Filter.html#map/2) [move\_exprs\_to\_relationship\_path(refs, path)](Ash.Filter.html#move_exprs_to_relationship_path/2) [move\_to\_relationship\_path(expression, relationship\_path)](Ash.Filter.html#move_to_relationship_path/2) [parse(resource, statement, context \\\\ %{})](Ash.Filter.html#parse/3) Parses a filter statement [parse!(resource, statement, context \\\\ %{})](Ash.Filter.html#parse!/3) Parses a filter statement [parse\_input(resource, statement)](Ash.Filter.html#parse_input/2) Parses a filter statement, accepting only public attributes/relationships, honoring field policies &amp; related resource policies. [parse\_input!(resource, statement)](Ash.Filter.html#parse_input!/2) Parses a filter statement, accepting only public attributes/relationships, honoring field policies &amp; related resource policies, raising on errors. [prefix\_refs(expr, path)](Ash.Filter.html#prefix_refs/2) [put\_at\_path(value, list)](Ash.Filter.html#put_at_path/2) [relationship\_paths(filter\_or\_expression, include\_exists? \\\\ false, with\_refs? \\\\ false, expand\_aggregates? \\\\ false)](Ash.Filter.html#relationship_paths/4) [run\_other\_data\_layer\_filters(domain, resource, filter, tenant)](Ash.Filter.html#run_other_data_layer_filters/4) [strict\_subset\_of(filter, candidate)](Ash.Filter.html#strict_subset_of/2) Returns true if the second argument is a strict subset (always returns the same or less data) of the first [strict\_subset\_of?(filter, candidate)](Ash.Filter.html#strict_subset_of?/2) [to\_simple\_filter(map, opts \\\\ \[\])](Ash.Filter.html#to_simple_filter/2) Transform an expression based filter to a simple filter, which is just a list of predicates [update\_aggregates(expression, mapper, nested\_path \\\\ \[\], parent\_paths \\\\ \[\])](Ash.Filter.html#update_aggregates/4) [used\_aggregates(filter, relationship\_path \\\\ \[\], return\_refs? \\\\ false)](Ash.Filter.html#used_aggregates/3) [used\_calculations(filter, resource, relationship\_path \\\\ \[\], calculations \\\\ %{}, aggregates \\\\ %{}, return\_refs? \\\\ false)](Ash.Filter.html#used_calculations/6) # [](Ash.Filter.html#types)Types [](Ash.Filter.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L216) ``` @type t() :: %Ash.Filter{expression: term(), resource: term()} ``` # [](Ash.Filter.html#functions)Functions [](Ash.Filter.html#add_to_filter/6) # add\_to\_filter(base, addition, op \\\\ :and, aggregates \\\\ %{}, calculations \\\\ %{}, context \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L870) [](Ash.Filter.html#add_to_filter!/6) # add\_to\_filter!(base, addition, op \\\\ :and, aggregates \\\\ %{}, calculations \\\\ %{}, context \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L851) [](Ash.Filter.html#builtin_functions/0) # builtin\_functions() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L219) [](Ash.Filter.html#builtin_operators/0) # builtin\_operators() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L220) [](Ash.Filter.html#builtin_predicate_operators/0) # builtin\_predicate\_operators() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L221) [](Ash.Filter.html#builtins/0) # builtins() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L218) [](Ash.Filter.html#custom_expression/2) # custom\_expression(name, args) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L3406) [](Ash.Filter.html#do_hydrate_refs/2) # do\_hydrate\_refs(filter, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L3427) [](Ash.Filter.html#fetch_simple_equality_predicate/2) # fetch\_simple\_equality\_predicate(expression, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L645) ``` @spec fetch_simple_equality_predicate(Ash.Expr.t(), atom()) :: {:ok, term()} | :error ``` Can be used to find a simple equality predicate on an attribute Use this when your attribute is configured with `filterable? :simple_equality`, and you want to to find the value that it is being filtered on with (if any). [](Ash.Filter.html#find/4) # find(expr, pred, ors? \\\\ true, ands? \\\\ true) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L676) Find an expression inside of a filter that matches the provided predicate [](Ash.Filter.html#find_simple_equality_predicate/2) # find\_simple\_equality\_predicate(expression, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L624) Can be used to find a simple equality predicate on an attribute Prefer [`fetch_simple_equality_predicate/2`](Ash.Filter.html#fetch_simple_equality_predicate/2). [](Ash.Filter.html#find_value/2) # find\_value(expr, pred) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L671) [](Ash.Filter.html#flat_map/2) # flat\_map(expression, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L1269) [](Ash.Filter.html#get_filter/2) # get\_filter(resource, id) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L450) Returns a filter statement that would find a single record based on the input. For example: ``` iex> get_filter(MyApp.Post, 1) {:ok, %{id: 1}} #using primary key iex> get_filter(MyApp.Post, id: 1) {:ok, %{id: 1}} #using primary key iex> get_filter(MyApp.Post, author_id: 1, publication_id: 2, first_name: "fred") {:ok, %{author_id: 1, publication_id: 1}} # using a unique identity iex> get_filter(MyApp.Post, first_name: "fred") :error # not enough information ``` [](Ash.Filter.html#get_function/3) # get\_function(key, resource, public?) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L4106) [](Ash.Filter.html#get_operator/1) # get\_operator(key) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L4139) [](Ash.Filter.html#get_predicate_function/3) # get\_predicate\_function(key, resource, public?) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L4096) [](Ash.Filter.html#hydrate_refs/2) # hydrate\_refs(value, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L3417) [](Ash.Filter.html#list_predicates/1) # list\_predicates(expression) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L2389) [](Ash.Filter.html#list_refs/5) # list\_refs(expression, no\_longer\_simple? \\\\ false, in\_an\_eq? \\\\ false, expand\_calculations? \\\\ false, expand\_get\_path? \\\\ false) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L2235) [](Ash.Filter.html#map/2) # map(filter, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L1184) [](Ash.Filter.html#move_exprs_to_relationship_path/2) # move\_exprs\_to\_relationship\_path(refs, path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L3837) [](Ash.Filter.html#move_to_relationship_path/2) # move\_to\_relationship\_path(expression, relationship\_path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L3843) [](Ash.Filter.html#parse/3) # parse(resource, statement, context \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L314) Parses a filter statement See the module documentation for more information on the supported formats for filter statements. ### [](Ash.Filter.html#parse/3-important)Important If you are trying to validate a filter supplied from an external/untrusted source, be sure to use [`parse_input/2`](Ash.Filter.html#parse_input/2) instead! The only difference is that it only accepts filters over public attributes/relationships. [](Ash.Filter.html#parse!/3) # parse!(resource, statement, context \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L290) Parses a filter statement See [`parse/2`](Ash.Filter.html#parse/2) for more [](Ash.Filter.html#parse_input/2) # parse\_input(resource, statement) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L249) Parses a filter statement, accepting only public attributes/relationships, honoring field policies &amp; related resource policies. See [`parse/2`](Ash.Filter.html#parse/2) for more [](Ash.Filter.html#parse_input!/2) # parse\_input!(resource, statement) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L275) Parses a filter statement, accepting only public attributes/relationships, honoring field policies &amp; related resource policies, raising on errors. See [`parse_input/2`](Ash.Filter.html#parse_input/2) for more [](Ash.Filter.html#prefix_refs/2) # prefix\_refs(expr, path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L1585) [](Ash.Filter.html#put_at_path/2) # put\_at\_path(value, list) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L848) [](Ash.Filter.html#relationship_paths/4) # relationship\_paths(filter\_or\_expression, include\_exists? \\\\ false, with\_refs? \\\\ false, expand\_aggregates? \\\\ false) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L1802) [](Ash.Filter.html#run_other_data_layer_filters/4) # run\_other\_data\_layer\_filters(domain, resource, filter, tenant) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L1378) [](Ash.Filter.html#strict_subset_of/2) # strict\_subset\_of(filter, candidate) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L917) Returns true if the second argument is a strict subset (always returns the same or less data) of the first [](Ash.Filter.html#strict_subset_of?/2) # strict\_subset\_of?(filter, candidate) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L929) [](Ash.Filter.html#to_simple_filter/2) # to\_simple\_filter(map, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L612) Transform an expression based filter to a simple filter, which is just a list of predicates Options: - `:skip_invalid?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If an invalid filter expression is reached that can't be used with a simple filter (like an `or` statement, or a non-predicate expression), it will be ignored instead of raising an error. The default value is `false`. [](Ash.Filter.html#update_aggregates/4) # update\_aggregates(expression, mapper, nested\_path \\\\ \[], parent\_paths \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L1311) [](Ash.Filter.html#used_aggregates/3) # used\_aggregates(filter, relationship\_path \\\\ \[], return\_refs? \\\\ false) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L814) [](Ash.Filter.html#used_calculations/6) # used\_calculations(filter, resource, relationship\_path \\\\ \[], calculations \\\\ %{}, aggregates \\\\ %{}, return\_refs? \\\\ false) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L750) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Filter.Predicate behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/predicate.ex#L1 "View Source") Represents a predicate which can be simplified and/or compared with other predicates Simplification and comparison will need more documentation, but ultimately it is the logic that allows us to have a flexible and powerful authorization system. # [](Ash.Filter.Predicate.html#summary)Summary ## [Types](Ash.Filter.Predicate.html#types) [comparison()](Ash.Filter.Predicate.html#t:comparison/0) [predicate()](Ash.Filter.Predicate.html#t:predicate/0) ## [Callbacks](Ash.Filter.Predicate.html#callbacks) [bulk\_compare(list)](Ash.Filter.Predicate.html#c:bulk_compare/1) As long as at least one predicate of the type defined in your module, (and this callback is implemented), it will be called with all of the other predicates present in a filter. The return value is relatively complex, but it should be a list of boolean statements. E.g. `{op, left, right}` and `{:not, predicate}` (nested as deep as necessary). [compare(predicate, predicate)](Ash.Filter.Predicate.html#c:compare/2) Compare two predicates. If possible, use [`bulk_compare/1`](Ash.Filter.Predicate.html#c:bulk_compare/1) instead [simplify(predicate)](Ash.Filter.Predicate.html#c:simplify/1) Simplify to a more primitive statement. ## [Functions](Ash.Filter.Predicate.html#functions) [compare(same, same)](Ash.Filter.Predicate.html#compare/2) Checks with each predicate module to see if it has a comparison with # [](Ash.Filter.Predicate.html#types)Types [](Ash.Filter.Predicate.html#t:comparison/0) # comparison() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/predicate.ex#L12) ``` @type comparison() :: :unknown | :right_includes_left | :left_includes_right | :mutually_inclusive | :mutually_exclusive ``` [](Ash.Filter.Predicate.html#t:predicate/0) # predicate() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/predicate.ex#L10) ``` @type predicate() :: struct() ``` # [](Ash.Filter.Predicate.html#callbacks)Callbacks [](Ash.Filter.Predicate.html#c:bulk_compare/1) # bulk\_compare(list) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/predicate.ex#L33) ``` @callback bulk_compare([predicate()]) :: term() ``` As long as at least one predicate of the type defined in your module, (and this callback is implemented), it will be called with all of the other predicates present in a filter. The return value is relatively complex, but it should be a list of boolean statements. E.g. `{op, left, right}` and `{:not, predicate}` (nested as deep as necessary). The best way to do it is to find lists of predicates that are mutually exclusive or mutually inclusive, and pass those lists into [`Ash.SatSolver.mutually_exclusive/1`](Ash.SatSolver.html#mutually_exclusive/1) and [`Ash.SatSolver.mutually_inclusive/1`](Ash.SatSolver.html#mutually_inclusive/1) [](Ash.Filter.Predicate.html#c:compare/2) # compare(predicate, predicate) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/predicate.ex#L20) ``` @callback compare(predicate(), predicate()) :: comparison() ``` Compare two predicates. If possible, use [`bulk_compare/1`](Ash.Filter.Predicate.html#c:bulk_compare/1) instead [](Ash.Filter.Predicate.html#c:simplify/1) # simplify(predicate) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/predicate.ex#L42) ``` @callback simplify(predicate()) :: term() ``` Simplify to a more primitive statement. For example, `x in [1, 2]` simplifies to `x == 1 or x == 2`. Simplifying to filter expressions that already have comparisons lets you avoid writing that logic for a given predicate. # [](Ash.Filter.Predicate.html#functions)Functions [](Ash.Filter.Predicate.html#compare/2) # compare(same, same) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/predicate.ex#L50) Checks with each predicate module to see if it has a comparison with [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Filter.Runtime (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/runtime.ex#L1 "View Source") Checks a record to see if it matches a filter statement. We can't always tell if a record matches a filter statement, and as such this function may return `:unknown`. Additionally, some expressions wouldn't ever make sense outside of the context of the data layer, and will always be an error. For example, if you used the trigram search features in `ash_postgres`. That logic would need to be handwritten in Elixir and would need to be a *perfect* copy of the postgres implementation. That isn't a realistic goal. This generally should not affect anyone using the standard framework features, but if you were to attempt to use this module with a data layer like `ash_postgres`, certain expressions will behave unpredictably. # [](Ash.Filter.Runtime.html#summary)Summary ## [Functions](Ash.Filter.Runtime.html#functions) [filter\_matches(domain, records, filter, opts \\\\ \[\])](Ash.Filter.Runtime.html#filter_matches/4) Removes any records that don't match the filter. Automatically loads if necessary. If there are any ambiguous terms in the filter (e.g things that could only be determined by data layer), it is assumed that they are not matches. [old\_get\_related(records, list, unknown\_on\_unknown\_refs?, join\_filters, parent\_stack, domain)](Ash.Filter.Runtime.html#old_get_related/6) # [](Ash.Filter.Runtime.html#functions)Functions [](Ash.Filter.Runtime.html#filter_matches/4) # filter\_matches(domain, records, filter, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/runtime.ex#L24) Removes any records that don't match the filter. Automatically loads if necessary. If there are any ambiguous terms in the filter (e.g things that could only be determined by data layer), it is assumed that they are not matches. [](Ash.Filter.Runtime.html#old_get_related/6) # old\_get\_related(records, list, unknown\_on\_unknown\_refs?, join\_filters, parent\_stack, domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/runtime.ex#L1256) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Filter.Simple (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L223 "View Source") Represents a simplified filter, with a simple list of predicates [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Filter.Simple.Not (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/filter/filter.ex#L227 "View Source") A negated predicate [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.ForbiddenField (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/forbidden_field.ex#L1 "View Source") Represents a field that was hidden due to authorization rules. # [](Ash.ForbiddenField.html#summary)Summary ## [Types](Ash.ForbiddenField.html#types) [field\_type()](Ash.ForbiddenField.html#t:field_type/0) [t()](Ash.ForbiddenField.html#t:t/0) # [](Ash.ForbiddenField.html#types)Types [](Ash.ForbiddenField.html#t:field_type/0) # field\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/forbidden_field.ex#L3) ``` @type field_type() :: :aggregate | :attribute | :calculation | :relationship ``` [](Ash.ForbiddenField.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/forbidden_field.ex#L4) ``` @type t() :: %Ash.ForbiddenField{ field: atom(), original_value: term(), type: field_type() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Generator (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L1 "View Source") Tools for generating input to Ash resource actions and for generating seed data. ## [](Ash.Generator.html#module-using-ash-generator)Using Ash.Generator To define generators for your tests, `use Ash.Generator`, and define functions that use [`changeset_generator/3`](Ash.Generator.html#changeset_generator/3) and/or [`seed_generator/2`](Ash.Generator.html#seed_generator/2). ``` defmodule YourApp.Generator do use Ash.Generator # using `seed_generator`, bypasses the action and saves directly to the data layer def blog_post(opts \\ []) do seed_generator( %MyApp.Blog.Post{ name: sequence(:title, &"My Blog Post #{&1}") text: StreamData.repeatedly(fn -> Faker.Lorem.paragraph() end) }, overrides: opts ) end # using `changeset_generator`, calls the action when passed to `generate` def blog_post_comment(opts \\ []) do blog_post_id = opts[:blog_post_id] || once(:default_blog_post_id, fn -> generate(blog_post()).id end) changeset_generator( MyApp.Blog.Comment, :create, defaults: [ blog_post_id: blog_post_id ], overrides: opts ) end end ``` Then, in your tests, you can `import YourApp.Generator`, and use [`generate/1`](Ash.Generator.html#generate/1) and `generate_many/1` to generate data. For example: ``` import YourApp.Generator test "`comment_count` on blog_post shows the count of comments" do blog_post = generate(blog_post()) assert Ash.load!(blog_post, :comment_count).comment_count == 0 generate_many(blog_post_comment(blog_post_id: blog_post.id), 10) assert Ash.load!(blog_post, :comment_count).comment_count == 10 end ``` ## [](Ash.Generator.html#module-about-generators)About Generators These generators are backed by [`StreamData`](../stream_data/1.1.2/StreamData.html), and are ready for use with proeprty testing via [`ExUnitProperties`](../stream_data/1.1.2/ExUnitProperties.html) Many functions in this module support "overrides", which allow passing down either constant values or your own [`StreamData`](../stream_data/1.1.2/StreamData.html) generators. For example: ``` # All generated posts will have text as `"text"`. Equivalent to providing `StreamData.constant("text")`. Ash.Generator.seed_input(Post, %{text: "text"}) ``` # [](Ash.Generator.html#summary)Summary ## [Types](Ash.Generator.html#types) [overrides()](Ash.Generator.html#t:overrides/0) A map or keyword of data generators or constant values to use in place of defaults. [stream\_data()](Ash.Generator.html#t:stream_data/0) An instance of [`StreamData`](../stream_data/1.1.2/StreamData.html), gotten from one of the functions in that module. ## [Functions](Ash.Generator.html#functions) [action\_input(resource\_or\_record, action, generators \\\\ %{})](Ash.Generator.html#action_input/3) Generate input meant to be passed into a resource action. [changeset(resource\_or\_record, action, generators \\\\ %{}, changeset\_options \\\\ \[\])](Ash.Generator.html#changeset/4) Creates the input for the provided action with [`action_input/3`](Ash.Generator.html#action_input/3), and creates a changeset for that action with that input. [changeset\_generator(resource, action, opts \\\\ \[\])](Ash.Generator.html#changeset_generator/3) A generator of seedable records, to be passed to [`generate/1`](Ash.Generator.html#generate/1) or `generate_many/1` [generate(changeset)](Ash.Generator.html#generate/1) Takes one value from a changeset or seed generator and calls `Ash.create!` on it. [generate\_many(changeset\_generator, count)](Ash.Generator.html#generate_many/2) Takes `count` values from a changeset or seed generator and passes their inputs into `Ash.bulk_create!` or `Ash.Seed.seed!` respectively. [initialize\_once(identifier)](Ash.Generator.html#initialize_once/1) Starts and links an agent for a [`once/2`](Ash.Generator.html#once/2), or returns the existing agent pid if it already exists. [initialize\_sequence(identifier)](Ash.Generator.html#initialize_sequence/1) Starts and links an agent for a sequence, or returns the existing agent pid if it already exists. [many\_changesets(resource\_or\_record, action, count, generators \\\\ %{}, changeset\_options \\\\ \[\])](Ash.Generator.html#many_changesets/5) Generate `count` changesets and return them as a list. [many\_queries(resource, action, count, generators \\\\ %{}, changeset\_options \\\\ \[\])](Ash.Generator.html#many_queries/5) Generate `count` queries and return them as a list. [mixed\_map(map, keys)](Ash.Generator.html#mixed_map/2) Creates a generator of maps where all keys are required except the list provided [next\_in\_sequence(identifier, fun, sequencer \\\\ fn i -&gt; (i || -1) + 1 end)](Ash.Generator.html#next_in_sequence/3) Gets the next value for a given sequence identifier. [once(identifier, generator)](Ash.Generator.html#once/2) Run the provided function or enumerable (i.e generator) only once. [query(resource, action, generators \\\\ %{}, query\_options \\\\ \[\])](Ash.Generator.html#query/4) Creates the input for the provided action with [`action_input/3`](Ash.Generator.html#action_input/3), and returns a query for that action with that input. [seed!(resource, generators \\\\ %{})](Ash.Generator.html#seed!/2) Gets input using [`seed_input/2`](Ash.Generator.html#seed_input/2) and passes it to [`Ash.Seed.seed!/2`](Ash.Seed.html#seed!/2), returning the result [seed\_generator(record, opts \\\\ \[\])](Ash.Generator.html#seed_generator/2) A generator of seedable records, to be passed to [`generate/1`](Ash.Generator.html#generate/1) or `generate_many/1` [seed\_input(resource, generators \\\\ %{})](Ash.Generator.html#seed_input/2) Generate input meant to be passed into [`Ash.Seed.seed!/2`](Ash.Seed.html#seed!/2). [seed\_many!(resource, n, generators \\\\ %{})](Ash.Generator.html#seed_many!/3) Generates an input `n` times, and passes them all to seed, returning the list of seeded items. [sequence(identifier, generator, sequencer \\\\ fn i -&gt; (i || -1) + 1 end)](Ash.Generator.html#sequence/3) Generate globally unique values. [stop\_once(identifier)](Ash.Generator.html#stop_once/1) Stops the agent for a [`once/2`](Ash.Generator.html#once/2). [stop\_sequence(identifier)](Ash.Generator.html#stop_sequence/1) Stops the agent for a sequence. # [](Ash.Generator.html#types)Types [](Ash.Generator.html#t:overrides/0) # overrides() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L109) ``` @type overrides() :: %{required(term()) => stream_data() | term()} | Keyword.t(stream_data() | term()) ``` A map or keyword of data generators or constant values to use in place of defaults. Many functions in [`Ash.Generator`](Ash.Generator.html) support `overrides`, allowing to customize the default generated values. [](Ash.Generator.html#t:stream_data/0) # stream\_data() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L115) ``` @type stream_data() :: Enumerable.t() ``` An instance of [`StreamData`](../stream_data/1.1.2/StreamData.html), gotten from one of the functions in that module. # [](Ash.Generator.html#functions)Functions [](Ash.Generator.html#action_input/3) # action\_input(resource\_or\_record, action, generators \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L672) ``` @spec action_input( Ash.Resource.t() | Ash.Resource.record(), action :: atom(), generators :: overrides() ) :: map() ``` Generate input meant to be passed into a resource action. Arguments that are passed to a `manage_relationship` are excluded, and you will have to generate them yourself by passing your own generators/values down. See the module documentation for more. [](Ash.Generator.html#changeset/4) # changeset(resource\_or\_record, action, generators \\\\ %{}, changeset\_options \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L702) ``` @spec changeset( Ash.Resource.t(), action :: atom(), overrides(), changeset_options :: Keyword.t() ) :: Ash.Changeset.t() ``` Creates the input for the provided action with [`action_input/3`](Ash.Generator.html#action_input/3), and creates a changeset for that action with that input. See [`action_input/3`](Ash.Generator.html#action_input/3) and the module documentation for more. [](Ash.Generator.html#changeset_generator/3) # changeset\_generator(resource, action, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L199) A generator of seedable records, to be passed to [`generate/1`](Ash.Generator.html#generate/1) or `generate_many/1` See [`changeset_generator/3`](Ash.Generator.html#changeset_generator/3) for the equivalent construct for cases when you want to call resource actions as opposed to seed directly to the data layer. ## [](Ash.Generator.html#changeset_generator/3-examples)Examples ``` iex> changeset_generator(MyApp.Blog.Post, :create, defaults: [title: sequence(:blog_post_title, &"My Blog Post #{&1}")]) |> generate() %Ash.Changeset{...} ``` ## [](Ash.Generator.html#changeset_generator/3-usage-in-tests)Usage in tests This can be used to define generators in tests. A useful pattern is defining a function like so: ``` def blog_post(opts \ []) do changeset_generator( MyApp.Blog.Post, :create, defaults: [ name: sequence(:blog_post_title, &"My Blog Post #{&1}") text: StreamData.repeatedly(fn -> Faker.Lorem.paragraph() end) ], overrides: opts ) end ``` See the [`Ash.Generator`](Ash.Generator.html) moduledocs for more information. ## [](Ash.Generator.html#changeset_generator/3-options)Options - `:defaults` - A keyword list of values or generators, used as inputs. Can also be a function when using the `:uses` option. - `:overrides` - A keyword list or map of `t:overrides()` - `:actor` - Passed through to the changeset - `:tenant` - Passed through to the changeset - `:uses` - A map of generators that are passed into your `defaults`. `defaults` must be a function. This is useful when multiple things in your `defaults` need to use the same generated value. - `:authorize?` - Passed through to the changeset - `:context` - Passed through to the changeset - `:after_action` - A one argument function that takes the result and returns a new result to run after the record is creatd. ## [](Ash.Generator.html#changeset_generator/3-the-uses-option)The `uses` option ``` def blog_post(opts \ []) do changeset_generator( MyApp.Blog.Post, :create, uses: [ author: author() # A function using `changeset_generator` just like this one. ], defaults: fn %{author: author} -> author = generate(author) [ name: sequence(:blog_post_title, &"My Blog Post #{&1}") author_name: author.name, text: StreamData.repeatedly(fn -> Faker.Lorem.paragraph() end) ] end overrides: opts ) end ``` [](Ash.Generator.html#generate/1) # generate(changeset) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L586) ``` @spec generate(stream_data() | Ash.Changeset.t() | Ash.Resource.record()) :: Ash.Resource.record() ``` Takes one value from a changeset or seed generator and calls `Ash.create!` on it. Passes through resource structs without doing anything. Creates a changeset if given [](Ash.Generator.html#generate_many/2) # generate\_many(changeset\_generator, count) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L614) Takes `count` values from a changeset or seed generator and passes their inputs into `Ash.bulk_create!` or `Ash.Seed.seed!` respectively. [](Ash.Generator.html#initialize_once/1) # initialize\_once(identifier) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L490) ``` @spec initialize_once(atom()) :: pid() ``` Starts and links an agent for a [`once/2`](Ash.Generator.html#once/2), or returns the existing agent pid if it already exists. See [`once/2`](Ash.Generator.html#once/2) for more. [](Ash.Generator.html#initialize_sequence/1) # initialize\_sequence(identifier) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L519) ``` @spec initialize_sequence(atom()) :: pid() ``` Starts and links an agent for a sequence, or returns the existing agent pid if it already exists. See [`sequence/3`](Ash.Generator.html#sequence/3) for more. [](Ash.Generator.html#many_changesets/5) # many\_changesets(resource\_or\_record, action, count, generators \\\\ %{}, changeset\_options \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L726) ``` @spec many_changesets( Ash.Resource.t(), action :: atom(), count :: pos_integer(), overrides(), changeset_options :: Keyword.t() ) :: [Ash.Changeset.t()] ``` Generate `count` changesets and return them as a list. [](Ash.Generator.html#many_queries/5) # many\_queries(resource, action, count, generators \\\\ %{}, changeset\_options \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L771) ``` @spec many_queries( Ash.Resource.t(), action :: atom(), count :: pos_integer(), overrides(), changeset_options :: Keyword.t() ) :: [Ash.Query.t()] ``` Generate `count` queries and return them as a list. [](Ash.Generator.html#mixed_map/2) # mixed\_map(map, keys) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L817) ``` @spec mixed_map(map(), [term()]) :: stream_data() ``` Creates a generator of maps where all keys are required except the list provided ## [](Ash.Generator.html#mixed_map/2-example)Example ``` iex> mixed_map(%{a: StreamData.constant(1), b: StreamData.constant(2)}, [:b]) |> Enum.take(2) [%{a: 1}, %{a: 1, b: 2}] ``` [](Ash.Generator.html#next_in_sequence/3) # next\_in\_sequence(identifier, fun, sequencer \\\\ fn i -&gt; (i || -1) + 1 end) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L800) Gets the next value for a given sequence identifier. See [`sequence/3`](Ash.Generator.html#sequence/3) for more. This is equivalent to `identifier |> Ash.Generator.sequence(fun, sequencer) |> Enum.at(0)` [](Ash.Generator.html#once/2) # once(identifier, generator) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L432) ``` @spec once(pid() | atom(), (-> value) | Enumerable.t(value)) :: StreamData.t(value) when value: term() ``` Run the provided function or enumerable (i.e generator) only once. This is useful for ensuring that some piece of data is generated a single time during a test. The lifecycle of this generator is tied to the process that initially starts it. In general, that will be the test. In the rare case where you are running async processes that need to share a sequence that is not created in the test process, you can initialize a sequence in the test using [`initialize_once/1`](Ash.Generator.html#initialize_once/1). Example: ``` iex> Ash.Generator.once(:user, fn -> register_user(...) end) |> Enum.at(0) %User{id: 1} # created the user iex> Ash.Generator.once(:user, fn -> register_user(...) end) |> Enum.at(0) %User{id: 1} # reused the last user ``` [](Ash.Generator.html#query/4) # query(resource, action, generators \\\\ %{}, query\_options \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L757) ``` @spec query( Ash.Resource.t(), action :: atom(), overrides(), query_options :: Keyword.t() ) :: Ash.Query.t() ``` Creates the input for the provided action with [`action_input/3`](Ash.Generator.html#action_input/3), and returns a query for that action with that input. See [`action_input/3`](Ash.Generator.html#action_input/3) and the module documentation for more. [](Ash.Generator.html#seed!/2) # seed!(resource, generators \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L557) Gets input using [`seed_input/2`](Ash.Generator.html#seed_input/2) and passes it to [`Ash.Seed.seed!/2`](Ash.Seed.html#seed!/2), returning the result [](Ash.Generator.html#seed_generator/2) # seed\_generator(record, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L316) ``` @spec seed_generator( Ash.Resource.record() | (map() -> Ash.Resource.record()), opts :: Keyword.t() ) :: stream_data() ``` A generator of seedable records, to be passed to [`generate/1`](Ash.Generator.html#generate/1) or `generate_many/1` See [`changeset_generator/3`](Ash.Generator.html#changeset_generator/3) for the equivalent construct for cases when you want to call resource actions as opposed to seed directly to the data layer. ## [](Ash.Generator.html#seed_generator/2-examples)Examples ``` iex> seed_generator(%MyApp.Blog.Post{name: sequence(:blog_post_title, &"My Blog Post #{&1}")}) |> generate() %Tunez.Music.Artist{name: "Artist 1"} ``` ## [](Ash.Generator.html#seed_generator/2-usage-in-tests)Usage in tests This can be used to define seed generators in tests. A useful pattern is defining a function like so: ``` def blog_post(opts \ []) do seed_generator( %MyApp.Blog.Post{ name: sequence(:blog_post_title, &"My Blog Post #{&1}") text: StreamData.repeatedly(fn -> Faker.Lorem.paragraph() end) }, overrides: opts ) end ``` See the [`Ash.Generator`](Ash.Generator.html) moduledocs for more information. ## [](Ash.Generator.html#seed_generator/2-options)Options - `:overrides` - A keyword list or map of `t:overrides()` - `:actor` - Passed through to the changeset - `:tenant` - Passed through to the changeset - `:uses` - A map of generators that are passed into the first argument, if it is a function. - `:authorize?` - Passed through to the changeset - `:context` - Passed through to the changeset - `:after_action` - A one argument function that takes the result and returns a new result to run after the record is creatd. [](Ash.Generator.html#seed_input/2) # seed\_input(resource, generators \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L782) ``` @spec seed_input(Ash.Resource.t(), map()) :: StreamData.t(map()) ``` Generate input meant to be passed into [`Ash.Seed.seed!/2`](Ash.Seed.html#seed!/2). A map of custom [`StreamData`](../stream_data/1.1.2/StreamData.html) generators can be provided to add to or overwrite the generated input, for example: `Ash.Generator.seed_input(Post, %{text: StreamData.constant("Post")})` [](Ash.Generator.html#seed_many!/3) # seed\_many!(resource, n, generators \\\\ %{}) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L568) Generates an input `n` times, and passes them all to seed, returning the list of seeded items. [](Ash.Generator.html#sequence/3) # sequence(identifier, generator, sequencer \\\\ fn i -&gt; (i || -1) + 1 end) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L391) ``` @spec sequence(pid() | atom(), (iterator | nil -> value), (iterator | nil -> iterator)) :: StreamData.t(value) when iterator: term(), value: term() ``` Generate globally unique values. This is useful for generating values that are unique across all resources, such as email addresses, or for generating values that are unique across a single resource, such as identifiers. The values will be unique for anything using the same sequence name. The lifecycle of this generator is tied to the process that initially starts it. In general, that will be the test. In the rare case where you are running async processes that need to share a sequence that is not created in the test process, you can initialize a sequence in the test using [`initialize_sequence/1`](Ash.Generator.html#initialize_sequence/1). Example: ``` Ash.Generator.sequence(:unique_email, fn i -> "user#{i}@example.com" end) |> Enum.take(3) iex> ["user0@example.com", "user1@example.com", "user2@example.com"] ``` ## [](Ash.Generator.html#sequence/3-using-a-different-sequencer)Using a different sequencer By default we use an incrementing integer starting at 0. However, if you want to use something else, you can provide your own sequencer. The initial value will be `nil`, which you can use to detect that you are the start of the sequence. Example: ``` Ash.Generator.sequence(:unique_email, fn i -> "user#{i}@example.com" end, fn num -> (num || 1) - 1 end) |> Enum.take(3) iex> ["user0@example.com", "user-1@example.com", "user-2@example.com"] ``` [](Ash.Generator.html#stop_once/1) # stop\_once(identifier) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L507) Stops the agent for a [`once/2`](Ash.Generator.html#once/2). See [`once/2`](Ash.Generator.html#once/2) for more. [](Ash.Generator.html#stop_sequence/1) # stop\_sequence(identifier) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/generator/generator.ex#L549) Stops the agent for a sequence. See [`sequence/3`](Ash.Generator.html#sequence/3) for more. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1 "View Source") The primary interface to call actions and interact with resources. # [](Ash.html#summary)Summary ## [Types](Ash.html#types) [actor()](Ash.html#t:actor/0) [aggregate()](Ash.html#t:aggregate/0) [load\_statement()](Ash.html#t:load_statement/0) [page\_request()](Ash.html#t:page_request/0) [record\_or\_records()](Ash.html#t:record_or_records/0) [record\_with\_args()](Ash.html#t:record_with_args/0) [resource\_with\_args()](Ash.html#t:resource_with_args/0) ## [Functions](Ash.html#functions) [aggregate(query, aggregate\_or\_aggregates, opts \\\\ \[\])](Ash.html#aggregate/3) Runs an aggregate or aggregates over a resource query [aggregate!(query, aggregate\_or\_aggregates, opts \\\\ \[\])](Ash.html#aggregate!/3) Runs an aggregate or aggregates over a resource query. See [`aggregate/3`](Ash.html#aggregate/3) for more. [avg(query, field, opts \\\\ \[\])](Ash.html#avg/3) Fetches the average of all values of a given field. [avg!(query, field, opts \\\\ \[\])](Ash.html#avg!/3) Fetches the average of all values of a given field or raises an error. [bulk\_create(inputs, resource, action, opts \\\\ \[\])](Ash.html#bulk_create/4) Creates many records. [bulk\_create!(inputs, resource, action, opts \\\\ \[\])](Ash.html#bulk_create!/4) Creates many records, raising any errors that are returned. See [`bulk_create/4`](Ash.html#bulk_create/4) for more. [bulk\_destroy(query\_or\_stream, action, input, opts \\\\ \[\])](Ash.html#bulk_destroy/4) Destroys all items in the provided enumerable or query with the provided input. [bulk\_destroy!(stream\_or\_query, action, input, opts \\\\ \[\])](Ash.html#bulk_destroy!/4) Destroys all items in the provided enumerable or query with the provided input. [bulk\_update(query\_or\_stream, action, input, opts \\\\ \[\])](Ash.html#bulk_update/4) Updates all items in the provided enumerable or query with the provided input. [bulk\_update!(stream\_or\_query, action, input, opts \\\\ \[\])](Ash.html#bulk_update!/4) Updates all items in the provided enumerable or query with the provided input. [calculate(resource\_or\_record, calculation, opts \\\\ \[\])](Ash.html#calculate/3) Evaluates the calculation on the resource. [calculate!(resource\_or\_record, calculation, opts \\\\ \[\])](Ash.html#calculate!/3) Evaluates the calculation on the resource or raises an error. See [`calculate/3`](Ash.html#calculate/3) for more. [calculate\_opts()](Ash.html#calculate_opts/0) [can(action\_or\_query\_or\_changeset, actor, opts \\\\ \[\])](Ash.html#can/3) Returns whether or not the user can perform the action, or `:maybe`, returning any errors. [can?(action\_or\_query\_or\_changeset, actor, opts \\\\ \[\])](Ash.html#can?/3) Returns whether or not the user can perform the action, or raises on errors. [context\_to\_opts(map, add\_to \\\\ \[\])](Ash.html#context_to_opts/2) deprecated See [`Ash.Context.to_opts/2`](Ash.Context.html#to_opts/2). [count(query, opts \\\\ \[\])](Ash.html#count/2) Fetches the count of results that would be returned from a given query. [count!(query, opts \\\\ \[\])](Ash.html#count!/2) Fetches the count of results that would be returned from a given query, or raises an error. [create(changeset\_or\_resource, params\_or\_opts \\\\ %{}, opts \\\\ \[\])](Ash.html#create/3) Create a record. [create!(changeset\_or\_resource, params \\\\ %{}, opts \\\\ \[\])](Ash.html#create!/3) Create a record or raises an error. See [`create/2`](Ash.html#create/2) for more information. [destroy(changeset\_or\_record, opts \\\\ \[\])](Ash.html#destroy/2) Destroy a record. [destroy!(changeset\_or\_record, opts \\\\ \[\])](Ash.html#destroy!/2) Destroy a record. See [`destroy/2`](Ash.html#destroy/2) for more information. [exists(query, opts \\\\ \[\])](Ash.html#exists/2) Returns whether or not the query would return any results. [exists?(query, opts \\\\ \[\])](Ash.html#exists?/2) Returns whether or not the query would return any results, or raises an error. [first(query, field, opts \\\\ \[\])](Ash.html#first/3) Fetches the first value for a given field, or raises an error. [first!(query, field, opts \\\\ \[\])](Ash.html#first!/3) Fetches the first value for a given field. [get(resource, id, opts \\\\ \[\])](Ash.html#get/3) Get a record by an identifier. [get!(resource, id, opts \\\\ \[\])](Ash.html#get!/3) Get a record by an identifier, or raises an error. See [`get/3`](Ash.html#get/3) for more. [list(query, field, opts \\\\ \[\])](Ash.html#list/3) Fetches a list of all values of a given field. [list!(query, field, opts \\\\ \[\])](Ash.html#list!/3) Fetches a list of all values of a given field or raises an error. [load(data, query, opts \\\\ \[\])](Ash.html#load/3) Load fields or relationships on already fetched records. [load!(data, query, opts \\\\ \[\])](Ash.html#load!/3) Load fields or relationships on already fetched records. See [`load/3`](Ash.html#load/3) for more information. [max(query, field, opts \\\\ \[\])](Ash.html#max/3) Fetches the greatest of all values of a given field. [max!(query, field, opts \\\\ \[\])](Ash.html#max!/3) Fetches the greatest of all values of a given field or raises an error. [min(query, field, opts \\\\ \[\])](Ash.html#min/3) Fetches the least of all values of a given field. [min!(query, field, opts \\\\ \[\])](Ash.html#min!/3) Fetches the least of all values of a given field or raises an error. [page(page, n)](Ash.html#page/2) Fetch a page relative to the provided page. [page!(page, request)](Ash.html#page!/2) Fetch a page relative to the provided page or raises an error [read(query, opts \\\\ \[\])](Ash.html#read/2) Runs an [`Ash.Query`](Ash.Query.html). [read!(query, opts \\\\ \[\])](Ash.html#read!/2) Run an [`Ash.Query`](Ash.Query.html). See [`read/2`](Ash.html#read/2) for more. [read\_first(query, opts \\\\ \[\])](Ash.html#read_first/2) Runs a query on a resource, returning a first result, nil, or an error. [read\_first!(query, opts \\\\ \[\])](Ash.html#read_first!/2) Runs an Ash query, returning the first result or nil, or raising an error. See [`read_first/2`](Ash.html#read_first/2) for more. [read\_one(query, opts \\\\ \[\])](Ash.html#read_one/2) Runs a query on a resource, returning a single result, nil, or an error. [read\_one!(query, opts \\\\ \[\])](Ash.html#read_one!/2) Runs an ash query, returning a single result or raise an error. See [`read_one/2`](Ash.html#read_one/2) for more. [reload(record, opts \\\\ \[\])](Ash.html#reload/2) Refetches a record by primary key. See [`reload/2`](Ash.html#reload/2) for more. [reload!(record, opts \\\\ \[\])](Ash.html#reload!/2) Refetches a record by primary key or raises an error. See [`reload/2`](Ash.html#reload/2) for more. [run\_action(input, opts \\\\ \[\])](Ash.html#run_action/2) Runs a generic action. [run\_action!(input, opts \\\\ \[\])](Ash.html#run_action!/2) Runs a generic action or raises an error. See [`run_action/2`](Ash.html#run_action/2) for more [stream!(query, opts \\\\ \[\])](Ash.html#stream!/2) Streams the results of a query. [sum(query, field, opts \\\\ \[\])](Ash.html#sum/3) Fetches the sum of a given field. [sum!(query, field, opts \\\\ \[\])](Ash.html#sum!/3) Fetches the sum of a given field or raises an error. [update(changeset\_or\_record, params\_or\_opts \\\\ %{}, opts \\\\ \[\])](Ash.html#update/3) Update a record. [update!(changeset\_or\_record, params\_or\_opts \\\\ %{}, opts \\\\ \[\])](Ash.html#update!/3) Update a record. See [`update/2`](Ash.html#update/2) for more information. # [](Ash.html#types)Types [](Ash.html#t:actor/0) # actor() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1755) ``` @type actor() :: any() ``` [](Ash.html#t:aggregate/0) # aggregate() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L12) ``` @type aggregate() :: Ash.Query.Aggregate.t() | {name :: atom(), kind :: atom()} | {name :: atom(), kind :: atom(), opts :: Keyword.t()} ``` [](Ash.html#t:load_statement/0) # load\_statement() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L17) ``` @type load_statement() :: Ash.Query.t() | [atom()] | atom() | Keyword.t() | [atom() | {atom(), atom() | Keyword.t()}] ``` [](Ash.html#t:page_request/0) # page\_request() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L9) ``` @type page_request() :: :next | :prev | :first | :last | :self | integer() ``` [](Ash.html#t:record_or_records/0) # record\_or\_records() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1754) ``` @type record_or_records() :: Ash.Resource.record() | [Ash.Resource.record()] ``` [](Ash.html#t:record_with_args/0) # record\_with\_args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L26) ``` @type record_with_args() :: {Ash.Resource.record(), map() | Keyword.t()} ``` [](Ash.html#t:resource_with_args/0) # resource\_with\_args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L24) ``` @type resource_with_args() :: {Ash.Resource.t(), map() | Keyword.t()} ``` # [](Ash.html#functions)Functions [](Ash.html#aggregate/3) # aggregate(query, aggregate\_or\_aggregates, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L929) ``` @spec aggregate( Ash.Query.t() | Ash.Resource.t(), aggregates :: aggregate() | [aggregate()], opts :: Keyword.t() ) :: {:ok, term()} | {:error, Ash.Error.t()} ``` Runs an aggregate or aggregates over a resource query If you pass an `%Ash.Query.Aggregate{}`, gotten from `Ash.Query.Aggregate.new()`, the query provided as the first argument to this function will not apply. For this reason, it is preferred that you pass in the tuple format, i.e Prefer this: `Api.aggregate(query, {:count_of_things, :count})` Over this: `Api.aggregate(query, Ash.Query.Aggregate.new(...))` - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access [](Ash.html#aggregate!/3) # aggregate!(query, aggregate\_or\_aggregates, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L891) ``` @spec aggregate!( Ash.Query.t() | Ash.Resource.t(), aggregates :: aggregate() | [aggregate()], opts :: Keyword.t() ) :: term() | no_return() ``` Runs an aggregate or aggregates over a resource query. See [`aggregate/3`](Ash.html#aggregate/3) for more. [](Ash.html#avg/3) # avg(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1246) Fetches the average of all values of a given field. [](Ash.html#avg!/3) # avg!(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1268) Fetches the average of all values of a given field or raises an error. [](Ash.html#bulk_create/4) # bulk\_create(inputs, resource, action, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2375) ``` @spec bulk_create( Enumerable.t(map()), resource :: Ash.Resource.t(), action :: atom(), opts :: Keyword.t() ) :: Ash.BulkResult.t() | Enumerable.t( {:ok, Ash.Resource.record()} | {:error, Ash.Changeset.t() | Ash.Error.t()} | {:notification, Ash.Notifier.Notification.t()} ) ``` Creates many records. ## [](Ash.html#bulk_create/4-assumptions)Assumptions We assume that the input is a list of changesets all for the same action, or a list of input maps for the same action with the `:resource` and `:action` option provided to illustrate which action it is for. ## [](Ash.html#bulk_create/4-performance-feasibility)Performance/Feasibility The performance of this operation depends on the data layer in question. Data layers like AshPostgres will choose reasonable batch sizes in an attempt to handle large bulk actions, but that does not mean that you can pass a list of 500k inputs and expect things to go off without a hitch (although it might). If you need to do large data processing, you should look into projects like GenStage and Broadway. With that said, if you want to do things like support CSV upload and you place some reasonable limits on the size this is a great tool. You'll need to test it yourself, YMMV. Passing `return_records?: true` can significantly increase the time it takes to perform the operation, and can also make the operation completely unreasonable due to the memory requirement. If you want to do very large bulk creates and display all of the results, the suggestion is to annotate them with a "bulk\_create\_id" in the data layer, and then read the records with that `bulk_create_id` so that they can be retrieved later if necessary. ## [](Ash.html#bulk_create/4-changes-validations)Changes/Validations Changes will be applied in the order they are given on the actions as normal. Any change that exposes the `bulk_change` callbacks will be applied on the entire list. ## [](Ash.html#bulk_create/4-after-action-hooks)After Action Hooks The following requirements must be met for `after_action` hooks to function properly. If they are not met, and an after\_action hook being applied to a changeset in a `change`. 1. `return_records?` must be set to `true`. 2. The changeset must be setting the primary key as part of its changes, so that we know which result applies to which changeset. It is possible to use `after_action` hooks with `bulk_change/3`, but you need to return the hooks along with the changesets. This allows for setting up `after_action` hooks that don't need access to the returned record, or `after_action` hooks that can operate on the entire list at once. See the documentation for that callback for more on how to do accomplish that. ## [](Ash.html#bulk_create/4-options)Options - `:upsert?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If a conflict is found based on the primary key, the record is updated in the database (requires upsert support) The default value is `false`. - `:upsert_identity` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The identity to use when detecting conflicts for `upsert?`, e.g. `upsert_identity: :full_name`. By default, the primary key is used. Has no effect if `upsert?: true` is not provided - `:upsert_fields` - The fields to upsert. If not set, the action's `upsert_fields` is used. Unlike singular `create`, `bulk_create` with `upsert?` requires that `upsert_fields` be specified explicitly in one of these two locations. - `:after_action` (function of arity 2) - An after\_action hook to be added to each processed changeset - `:upsert_condition` ([`term/0`](../elixir/typespecs.html#built-in-types)) - An expression to check if the record should be updated when there's a conflict. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The action to use when building the read query. - `:assume_casted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting The default value is `false`. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to apply to records. Ignored if `return_records?` is not true. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:authorize_query_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Uses `authorize_with` if not set. Valid values are :filter, :error - `:authorize_changeset_with` - If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error. Uses `authorize_with` if not set. Valid values are :filter, :error - `:authorize_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Valid values are :filter, :error The default value is `:filter`. - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on each changeset - `:sorted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to sort results by their input position, in cases where `return_records?: true` was provided. The default value is `false`. - `:return_records?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts. The default value is `false`. - `:return_errors?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the errors that occur. Defaults to false to account for large inserts. The default value is `false`. - `:batch_size` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100. - `:return_stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned. Potential elements: `{:notification, notification}` - if `return_notifications?` is set to `true` `{:ok, record}` - if `return_records?` is set to `true` `{:error, error}` - an error that occurred. May be changeset or an invidual error. The default value is `false`. - `:return_nothing?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Mutes warnings about returning nothing. Only relevant if `return_stream?` is set to `true` and all other `return_*?` options are set to `false`. The default value is `false`. - `:stop_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. The default value is `false`. - `:notify?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to generate any notifications. If this is set to `true` then the data layer must return the results from each batch. This may be intensive for large bulk actions. Notifications will be automatically sent unless `return_notifications?` is set to `true`. The default value is `false`. - `:transaction` - Whether or not to wrap the entire execution in a transaction, each batch, or not at all. Keep in mind: `before_transaction` and `after_transaction` hooks attached to changesets will have to be run *inside* the transaction if you choose `transaction: :all`. Valid values are :all, :batch, false The default value is `:batch`. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously The default value is `0`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. [](Ash.html#bulk_create!/4) # bulk\_create!(inputs, resource, action, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2278) ``` @spec bulk_create!(Enumerable.t(map()), Ash.Resource.t(), atom(), Keyword.t()) :: Ash.BulkResult.t() | no_return() ``` Creates many records, raising any errors that are returned. See [`bulk_create/4`](Ash.html#bulk_create/4) for more. [](Ash.html#bulk_destroy/4) # bulk\_destroy(query\_or\_stream, action, input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2589) ``` @spec bulk_destroy( Enumerable.t(Ash.Resource.record()) | Ash.Query.t(), atom(), input :: map(), Keyword.t() ) :: Ash.BulkResult.t() ``` Destroys all items in the provided enumerable or query with the provided input. The input is a map of valid inputs for the action. The input will be applied to all records in the enumerable/query. If the data layer supports destroying from a query, and the destroy action can be done fully atomically, it will be updated in a single pass using the data layer. Otherwise, this will stream each record and update it. ## [](Ash.html#bulk_destroy/4-options)Options - `:resource` ([`Ash.Resource`](Ash.Resource.html)) - The resource being destroyed. This must be provided if the input given is a stream, so we know ahead of time what the resource being updated is. - `:stream_batch_size` ([`integer/0`](../elixir/typespecs.html#basic-types)) - Batch size to use if provided a query and the query must be streamed - `:authorize_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If a query is given, determines whether or not authorization is run on that query. The default value is `true`. - `:strategy` - The strategy or strategies to enable. :stream is used in all cases if the data layer does not support atomics. Valid values are :atomic, :atomic\_batches, :stream The default value is `:atomic`. - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter to apply to records. This is also applied to a stream of inputs. - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. Valid values are :keyset, :offset, :full\_read The default value is `:keyset`. - `:stream_with` - The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. Valid values are :keyset, :offset, :full\_read - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The action to use when building the read query. - `:assume_casted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting The default value is `false`. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to apply to records. Ignored if `return_records?` is not true. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:authorize_query_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Uses `authorize_with` if not set. Valid values are :filter, :error - `:authorize_changeset_with` - If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error. Uses `authorize_with` if not set. Valid values are :filter, :error - `:authorize_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Valid values are :filter, :error The default value is `:filter`. - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on each changeset - `:sorted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to sort results by their input position, in cases where `return_records?: true` was provided. The default value is `false`. - `:return_records?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts. The default value is `false`. - `:return_errors?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the errors that occur. Defaults to false to account for large inserts. The default value is `false`. - `:batch_size` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100. - `:return_stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned. Potential elements: `{:notification, notification}` - if `return_notifications?` is set to `true` `{:ok, record}` - if `return_records?` is set to `true` `{:error, error}` - an error that occurred. May be changeset or an invidual error. The default value is `false`. - `:return_nothing?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Mutes warnings about returning nothing. Only relevant if `return_stream?` is set to `true` and all other `return_*?` options are set to `false`. The default value is `false`. - `:stop_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. The default value is `false`. - `:notify?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to generate any notifications. If this is set to `true` then the data layer must return the results from each batch. This may be intensive for large bulk actions. Notifications will be automatically sent unless `return_notifications?` is set to `true`. The default value is `false`. - `:transaction` - Whether or not to wrap the entire execution in a transaction, each batch, or not at all. Keep in mind: `before_transaction` and `after_transaction` hooks attached to changesets will have to be run *inside* the transaction if you choose `transaction: :all`. Valid values are :all, :batch, false The default value is `:batch`. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously The default value is `0`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. [](Ash.html#bulk_destroy!/4) # bulk\_destroy!(stream\_or\_query, action, input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2531) ``` @spec bulk_destroy!( Enumerable.t(Ash.Resource.record()) | Ash.Query.t(), action :: atom(), input :: map(), opts :: Keyword.t() ) :: Ash.BulkResult.t() | no_return() ``` Destroys all items in the provided enumerable or query with the provided input. See [`bulk_destroy/4`](Ash.html#bulk_destroy/4) for more. [](Ash.html#bulk_update/4) # bulk\_update(query\_or\_stream, action, input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2480) ``` @spec bulk_update( Enumerable.t(Ash.Resource.record()) | Ash.Query.t(), atom(), input :: map(), Keyword.t() ) :: Ash.BulkResult.t() ``` Updates all items in the provided enumerable or query with the provided input. The input is a map of valid inputs for the action. The input will be applied to all records in the enumerable/query. If the data layer supports updating from a query, and the update action can be done fully atomically, it will be updated in a single pass using the data layer. Otherwise, this will stream each record and update it. ## [](Ash.html#bulk_update/4-options)Options - `:resource` ([`Ash.Resource`](Ash.Resource.html)) - The resource being updated. This must be provided if the input given is a stream, so we know ahead of time what the resource being updated is. - `:atomic_update` ([`map/0`](../elixir/typespecs.html#basic-types)) - A map of atomic updates to apply. See [`Ash.Changeset.atomic_update/3`](Ash.Changeset.html#atomic_update/3) for more. - `:stream_batch_size` ([`integer/0`](../elixir/typespecs.html#basic-types)) - Batch size to use if provided a query and the query must be streamed - `:authorize_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If a query is given, determines whether or not authorization is run on that query. The default value is `true`. - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter to apply to records. This is also applied to a stream of inputs. - `:strategy` - The strategy or strategies to enable. :stream is used in all cases if the data layer does not support atomics. Valid values are :atomic, :atomic\_batches, :stream The default value is `[:atomic]`. - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. Valid values are :keyset, :offset, :full\_read The default value is `:keyset`. - `:stream_with` - The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. Valid values are :keyset, :offset, :full\_read - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The action to use when building the read query. - `:assume_casted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting The default value is `false`. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to apply to records. Ignored if `return_records?` is not true. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:authorize_query_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Uses `authorize_with` if not set. Valid values are :filter, :error - `:authorize_changeset_with` - If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error. Uses `authorize_with` if not set. Valid values are :filter, :error - `:authorize_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Valid values are :filter, :error The default value is `:filter`. - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on each changeset - `:sorted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to sort results by their input position, in cases where `return_records?: true` was provided. The default value is `false`. - `:return_records?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts. The default value is `false`. - `:return_errors?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the errors that occur. Defaults to false to account for large inserts. The default value is `false`. - `:batch_size` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100. - `:return_stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned. Potential elements: `{:notification, notification}` - if `return_notifications?` is set to `true` `{:ok, record}` - if `return_records?` is set to `true` `{:error, error}` - an error that occurred. May be changeset or an invidual error. The default value is `false`. - `:return_nothing?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Mutes warnings about returning nothing. Only relevant if `return_stream?` is set to `true` and all other `return_*?` options are set to `false`. The default value is `false`. - `:stop_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. The default value is `false`. - `:notify?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to generate any notifications. If this is set to `true` then the data layer must return the results from each batch. This may be intensive for large bulk actions. Notifications will be automatically sent unless `return_notifications?` is set to `true`. The default value is `false`. - `:transaction` - Whether or not to wrap the entire execution in a transaction, each batch, or not at all. Keep in mind: `before_transaction` and `after_transaction` hooks attached to changesets will have to be run *inside* the transaction if you choose `transaction: :all`. Valid values are :all, :batch, false The default value is `:batch`. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously The default value is `0`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. [](Ash.html#bulk_update!/4) # bulk\_update!(stream\_or\_query, action, input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2422) ``` @spec bulk_update!( Enumerable.t(Ash.Resource.record()) | Ash.Query.t(), action :: atom(), input :: map(), opts :: Keyword.t() ) :: Ash.BulkResult.t() | no_return() ``` Updates all items in the provided enumerable or query with the provided input. See [`bulk_update/4`](Ash.html#bulk_update/4) for more. [](Ash.html#calculate/3) # calculate(resource\_or\_record, calculation, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1465) ``` @spec calculate( resource_or_record :: Ash.Resource.t() | Ash.Resource.record(), calculation :: atom(), opts :: Keyword.t() ) :: {:ok, term()} | {:error, term()} ``` Evaluates the calculation on the resource. If a record is provided, its field values will be used to evaluate the calculation. - `:args` ([`map/0`](../elixir/typespecs.html#basic-types)) - Values for arguments referenced by the calculation. The default value is `%{}`. - `:refs` ([`map/0`](../elixir/typespecs.html#basic-types)) - Values for references used by the calculation. The default value is `%{}`. - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The actor for handling [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates, supplied to calculation context. - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - The tenant, supplied to calculation context. - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not the request is being authorized, provided to calculation context. The default value is `true`. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer, provided to the calculation context. - `:record` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A record to use as the base of the calculation - `:data_layer?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Set to `true` to require that the value be computed within the data layer. Only works for calculations that define an expression. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use for the action [](Ash.html#calculate!/3) # calculate!(resource\_or\_record, calculation, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1435) ``` @spec calculate!( resource_or_record :: Ash.Resource.t() | Ash.Resource.record(), calculation :: atom(), opts :: Keyword.t() ) :: term() | no_return() ``` Evaluates the calculation on the resource or raises an error. See [`calculate/3`](Ash.html#calculate/3) for more. [](Ash.html#calculate_opts/0) # calculate\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L766) [](Ash.html#can/3) # can(action\_or\_query\_or\_changeset, actor, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1348) ``` @spec can(Ash.Can.subject(), actor(), Keyword.t()) :: {:ok, boolean() | :maybe} | {:ok, true, Ash.Changeset.t() | Ash.Query.t()} | {:ok, true, Ash.Changeset.t(), Ash.Query.t()} | {:ok, false, Exception.t()} | {:error, term()} ``` Returns whether or not the user can perform the action, or `:maybe`, returning any errors. In cases with "runtime" checks (checks after the action), we may not be able to determine an answer, and so the value `:maybe` will be returned from [`can/2`](Ash.html#can/2). The `can?` function assumes that `:maybe` means `true`. Keep in mind, this is just for doing things like "can they do this" in a UI, so assuming `:maybe` is `true` is fine. The actual action invocation will be properly checked regardless. If you have runtime checks, you may need to use `can` instead of `can?`, or configure what `:maybe` means. ### [](Ash.html#can/3-accepted-inputs)Accepted inputs You can pass many different inputs as the subject to [`can/3`](Ash.html#can/3). ``` # Can this user run this query. Ash.Query.t() # Can this user run this changeset. Ash.Changeset.t() # Can this user run this action. Ash.ActionInput.t() # Can this user run this action. {Ash.Resource.t(), :action} # Can this user run this action. {Ash.Resource.t(), %Action{}} # Can this user run this action with this input. {Ash.Resource.t(), :atom, %{...input}} # Can this user run this action with this input. {Ash.Resource.t(), %Action{}, %{...input}} ``` ### [](Ash.html#can/3-options)Options - `:maybe_is` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If the actor *may* be able to perform the action, what value should be returned. The default value is `:maybe`. - `:filter_with` - If set to `:error`, the query will raise an error on a match. If set to `:filter` the query will filter out unauthorized access. Valid values are :filter, :error The default value is `:filter`. - `:validate?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to treat an invalid action as a non-allowed action. The default value is `false`. - `:pre_flight?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not this is a pre\_flight check (which may perform optimized in-memory checks) or the final proper check. The default value is `true`. - `:run_queries?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to run queries. If set to `true`, `:maybe` will not be returned. The default value is `true`. - `:data` - The record or records specifically attempting to be acted upon. - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - The tenant to use for authorization - `:alter_source?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, the source being authorized is returned so it can be run. The default value is `false`. - `:base_query` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A base query on which to apply an generated filters - `:no_check?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not authorization must pass at the strict/filter step, or if post-checks are allowed to be run The default value is `false`. - `:on_must_pass_strict_check` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Override the value returned when `no_check?` is `true` but a check must be run. - `:atomic_changeset` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A base query on which to apply an generated filters - `:return_forbidden_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return a forbidden error in cases of not being authorized. The default value is `false`. [](Ash.html#can?/3) # can?(action\_or\_query\_or\_changeset, actor, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1288) ``` @spec can?(Ash.Can.subject(), actor(), Keyword.t()) :: boolean() | no_return() ``` Returns whether or not the user can perform the action, or raises on errors. Calls [`can/3`](Ash.html#can/3) with a `maybe_is: true`. See [`can/3`](Ash.html#can/3) for more info. ### [](Ash.html#can?/3-options)Options - `:maybe_is` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If the actor *may* be able to perform the action, what value should be returned. The default value is `true`. - `:filter_with` - If set to `:error`, the query will raise an error on a match. If set to `:filter` the query will filter out unauthorized access. Valid values are :filter, :error The default value is `:filter`. - `:validate?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to treat an invalid action as a non-allowed action. The default value is `false`. - `:pre_flight?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not this is a pre\_flight check (which may perform optimized in-memory checks) or the final proper check. The default value is `true`. - `:run_queries?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to run queries. If set to `true`, `:maybe` will not be returned. The default value is `true`. - `:data` - The record or records specifically attempting to be acted upon. - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - The tenant to use for authorization - `:alter_source?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, the source being authorized is returned so it can be run. The default value is `false`. - `:base_query` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A base query on which to apply an generated filters - `:no_check?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not authorization must pass at the strict/filter step, or if post-checks are allowed to be run The default value is `false`. - `:on_must_pass_strict_check` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Override the value returned when `no_check?` is `true` but a check must be run. - `:atomic_changeset` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A base query on which to apply an generated filters - `:return_forbidden_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return a forbidden error in cases of not being authorized. The default value is `false`. [](Ash.html#context_to_opts/2) # context\_to\_opts(map, add\_to \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2810) This function is deprecated. Converts a context map to opts to be passed into an action. . See [`Ash.Context.to_opts/2`](Ash.Context.html#to_opts/2). [](Ash.html#count/2) # count(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L964) Fetches the count of results that would be returned from a given query. [](Ash.html#count!/2) # count!(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L951) Fetches the count of results that would be returned from a given query, or raises an error. [](Ash.html#create/3) # create(changeset\_or\_resource, params\_or\_opts \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2218) ``` @spec create( changset_or_resource :: Ash.Changeset.t() | Ash.Resource.t(), params_or_opts :: map() | Keyword.t(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.record()} | {:ok, Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | {:error, term()} ``` Create a record. - `:upsert?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If a conflict is found based on the primary key, the record is updated in the database (requires upsert support) The default value is `false`. - `:return_skipped_upsert?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, and a record was *not* upserted because its filter prevented the upsert, the original record (which was *not* upserted) will be returned. The default value is `false`. - `:upsert_identity` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The identity to use when detecting conflicts for `upsert?`, e.g. `upsert_identity: :full_name`. By default, the primary key is used. Has no effect if `upsert?: true` is not provided - `:upsert_fields` - The fields to upsert. If not set, the action's upsert\_fields is used, and if that is not set, then any fields not being set to defaults are written. - `:upsert_condition` ([`term/0`](../elixir/typespecs.html#built-in-types)) - An expression to check if the record should be updated when there's a conflict. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the changeset [](Ash.html#create!/3) # create!(changeset\_or\_resource, params \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2191) ``` @spec create!( changset_or_resource :: Ash.Changeset.t() | Ash.Resource.t(), params_or_opts :: map() | Keyword.t(), opts :: Keyword.t() ) :: Ash.Resource.record() | {Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | no_return() ``` Create a record or raises an error. See [`create/2`](Ash.html#create/2) for more information. [](Ash.html#destroy/2) # destroy(changeset\_or\_record, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2768) ``` @spec destroy(Ash.Changeset.t() | Ash.Resource.record(), opts :: Keyword.t()) :: :ok | {:ok, Ash.Resource.record()} | {:ok, [Ash.Notifier.Notification.t()]} | {:ok, Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | {:error, term()} ``` Destroy a record. - `:return_destroyed?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the destroyed record is included in the return result, e.g `{:ok, destroyed}` or `{:ok, destroyed, notifications}` The default value is `false`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the changeset [](Ash.html#destroy!/2) # destroy!(changeset\_or\_record, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2739) ``` @spec destroy!(Ash.Changeset.t() | Ash.Resource.record(), opts :: Keyword.t()) :: :ok | Ash.Resource.record() | [Ash.Notifier.Notification.t()] | {Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | no_return() ``` Destroy a record. See [`destroy/2`](Ash.html#destroy/2) for more information. [](Ash.html#exists/2) # exists(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L997) Returns whether or not the query would return any results. [](Ash.html#exists?/2) # exists?(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L984) Returns whether or not the query would return any results, or raises an error. [](Ash.html#first/3) # first(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1024) Fetches the first value for a given field, or raises an error. [](Ash.html#first!/3) # first!(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1075) Fetches the first value for a given field. [](Ash.html#get/3) # get(resource, id, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1510) ``` @spec get(Ash.Resource.t(), term(), Keyword.t()) :: {:ok, Ash.Resource.record()} | {:error, term()} ``` Get a record by an identifier. For a resource with a composite primary key, pass a keyword list or map, e.g `Ash.get(MyResource, %{first_key: 1, second_key: 2})` Additionally, a keyword list or map of keys matching an identity can be provided. - `:error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not an error should be returned or raised when the record is not found. If set to false, `nil` will be returned. The default value is `true`. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Fields or relationships to load in the query. See [`Ash.Query.load/2`](Ash.Query.html#load/2) - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. Valid values are :filter, :error The default value is `:filter`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access [](Ash.html#get!/3) # get!(resource, id, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1481) ``` @spec get!(Ash.Resource.t(), term(), Keyword.t()) :: Ash.Resource.record() | no_return() ``` Get a record by an identifier, or raises an error. See [`get/3`](Ash.html#get/3) for more. [](Ash.html#list/3) # list(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1123) Fetches a list of all values of a given field. [](Ash.html#list!/3) # list!(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1163) Fetches a list of all values of a given field or raises an error. [](Ash.html#load/3) # load(data, query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1803) ``` @spec load( record_or_records :: Ash.Resource.record() | [Ash.Resource.record()], query :: load_statement(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.record() | [Ash.Resource.record()]} | {:error, term()} ``` Load fields or relationships on already fetched records. Accepts a list of non-loaded fields and loads them on the provided records or a query, in which case the loaded fields of the query are used. Relationship loads can be nested, for example: `Ash.load(record, [posts: [:comments]])`. - `:lazy?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, values will only be loaded if the related value isn't currently loaded. The default value is `false`. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access [](Ash.html#load!/3) # load!(data, query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1773) ``` @spec load!( record_or_records :: record_or_records() | {:ok, record_or_records()} | :error | {:error, term()} | :ok | Ash.Page.page(), query :: load_statement(), opts :: Keyword.t() ) :: Ash.Resource.record() | [Ash.Resource.record()] | no_return() ``` Load fields or relationships on already fetched records. See [`load/3`](Ash.html#load/3) for more information. [](Ash.html#max/3) # max(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1176) Fetches the greatest of all values of a given field. [](Ash.html#max!/3) # max!(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1198) Fetches the greatest of all values of a given field or raises an error. [](Ash.html#min/3) # min(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1211) Fetches the least of all values of a given field. [](Ash.html#min!/3) # min!(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1233) Fetches the least of all values of a given field or raises an error. [](Ash.html#page/2) # page(page, n) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1611) ``` @spec page(Ash.Page.page(), page_request()) :: {:ok, Ash.Page.page()} | {:error, Ash.Error.t()} ``` Fetch a page relative to the provided page. [](Ash.html#page!/2) # page!(page, request) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1600) ``` @spec page!(Ash.Page.page(), page_request()) :: Ash.Page.page() | no_return() ``` Fetch a page relative to the provided page or raises an error [](Ash.html#read/2) # read(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1994) ``` @spec read(Ash.Query.t() | Ash.Resource.t(), Keyword.t()) :: {:ok, [Ash.Resource.record()] | Ash.Page.page()} | {:error, term()} ``` Runs an [`Ash.Query`](Ash.Query.html). For more information on building a query, see [`Ash.Query`](Ash.Query.html). - `:page` - Pagination options, see [`Ash.read/2`](Ash.html#read/2) for more. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the query - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. Valid values are :filter, :error The default value is `:filter`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access ## [](Ash.html#read/2-pagination)Pagination #### Limit/offset pagination - `:offset` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to skip from the beginning of the query - `:limit` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in the page - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter to apply for pagination purposes, that should not be considered in the full count. This is used by the liveview paginator to only fetch the records that were *already* on the page when refreshing data, to avoid pages jittering. - `:count` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return the page with a full count of all records #### Keyset pagination - `:before` ([`String.t/0`](../elixir/String.html#t:t/0)) - Get records that appear before the provided keyset (mutually exclusive with `after`) - `:after` ([`String.t/0`](../elixir/String.html#t:t/0)) - Get records that appear after the provided keyset (mutually exclusive with `before`) - `:limit` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - How many records to include in the page - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - See the `filter` option for offset pagination, this behaves the same. - `:count` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return the page with a full count of all records [](Ash.html#read!/2) # read!(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1967) ``` @spec read!(Ash.Query.t() | Ash.Resource.t(), Keyword.t()) :: [Ash.Resource.record()] | Ash.Page.page() | no_return() ``` Run an [`Ash.Query`](Ash.Query.html). See [`read/2`](Ash.html#read/2) for more. [](Ash.html#read_first/2) # read\_first(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2139) ``` @spec read_first( resource_or_query :: Ash.Query.t() | Ash.Resource.t(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.record() | nil} | {:error, Ash.Error.t()} ``` Runs a query on a resource, returning a first result, nil, or an error. Query is automatically limited to only return one result, unlike `read_one/3` ## [](Ash.html#read_first/2-options)Options - `:not_found_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return an [`Ash.Error.Query.NotFound`](Ash.Error.Query.NotFound.html) if no record is found. The default value is `false`. - `:page` - Pagination options, see [`Ash.read/2`](Ash.html#read/2) for more. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the query - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. Valid values are :filter, :error The default value is `:filter`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access [](Ash.html#read_first!/2) # read\_first!(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2118) ``` @spec read_first!( resource_or_query :: Ash.Query.t() | Ash.Resource.t(), opts :: Keyword.t() ) :: Ash.Resource.record() | nil ``` Runs an Ash query, returning the first result or nil, or raising an error. See [`read_first/2`](Ash.html#read_first/2) for more. [](Ash.html#read_one/2) # read\_one(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2090) ``` @spec read_one( resource_or_query :: Ash.Query.t() | Ash.Resource.t(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.record() | nil} | {:error, Ash.Error.t()} ``` Runs a query on a resource, returning a single result, nil, or an error. If more than one result would be returned, an error is returned instead. ## [](Ash.html#read_one/2-options)Options - `:not_found_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return an [`Ash.Error.Query.NotFound`](Ash.Error.Query.NotFound.html) if no record is found. The default value is `false`. - `:page` - Pagination options, see [`Ash.read/2`](Ash.html#read/2) for more. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the query - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. Valid values are :filter, :error The default value is `:filter`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access [](Ash.html#read_one!/2) # read\_one!(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2061) ``` @spec read_one!( resource_or_query :: Ash.Query.t() | Ash.Resource.t(), opts :: Keyword.t() ) :: Ash.Resource.record() | nil ``` Runs an ash query, returning a single result or raise an error. See [`read_one/2`](Ash.html#read_one/2) for more. [](Ash.html#reload/2) # reload(record, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2046) ``` @spec reload(record :: Ash.Resource.record(), opts :: Keyword.t()) :: {:ok, Ash.Resource.record()} | {:error, Ash.Error.t()} ``` Refetches a record by primary key. See [`reload/2`](Ash.html#reload/2) for more. [](Ash.html#reload!/2) # reload!(record, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2031) ``` @spec reload!(record :: Ash.Resource.record(), opts :: Keyword.t()) :: Ash.Resource.record() | no_return() ``` Refetches a record by primary key or raises an error. See [`reload/2`](Ash.html#reload/2) for more. [](Ash.html#run_action/2) # run\_action(input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1406) ``` @spec run_action(input :: Ash.ActionInput.t(), opts :: Keyword.t()) :: :ok | {:ok, term()} | {:error, Ash.Error.t()} ``` Runs a generic action. Options: - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The actor for handling [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates, supplied to calculation context. - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - The tenant, supplied to calculation context. - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not the request should be authorized. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer, provided to the calculation context. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use for the action - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. [](Ash.html#run_action!/2) # run\_action!(input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1381) ``` @spec run_action!(input :: Ash.ActionInput.t(), opts :: Keyword.t()) :: term() | no_return() ``` Runs a generic action or raises an error. See [`run_action/2`](Ash.html#run_action/2) for more [](Ash.html#stream!/2) # stream!(query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1943) ``` @spec stream!(query :: Ash.Query.t() | Ash.Resource.t(), opts :: Keyword.t()) :: Enumerable.t(Ash.Resource.record()) ``` Streams the results of a query. ## [](Ash.html#stream!/2-strategies)Strategies There are three strategies supported, and the best one available is always chosen. They are, in order from best to worst: - `:keyset` - `:offset` - `:full_read` By default, only `:keyset` is supported. If you want to allow worse strategies to be used, pass the worst one you wish to allow as the `allow_stream_with` option, i.e `allow_stream_with: :full_read`. If you wish to specify a specific strategy to use, pass `stream_with: :strategy_name`. ### [](Ash.html#stream!/2-keyset)Keyset This utilizes keyset pagination to accomplish this stream. The action must support keyset pagination. This is the most efficient way to stream a query, because it works by using filters which can benefit from indexes in the data layer. ### [](Ash.html#stream!/2-offset)Offset This utilizes offset/limit to accomplish this stream. If the action supports offset pagination, that will be used. Otherwise, if the data layer supports limit/offset, then explicit limits/offsets will be used. This is a much less efficient way of streaming a resource than `keyset`. To use limit/offset to reliably stream, a sort must always be applied, and limit/offset in the data layer will generally require sorting the entire table to figure out what is in each batch. ### [](Ash.html#stream!/2-full-read)Full Read This reads the entire table into memory with no limit. This is, generally speaking, the least efficient. ## [](Ash.html#stream!/2-options)Options - `:batch_size` ([`integer/0`](../elixir/typespecs.html#basic-types)) - How many records to request in each query run. Defaults to the pagination limits on the resource, or 250. - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. Valid values are :keyset, :offset, :full\_read The default value is `:keyset`. - `:stream_with` - The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. Valid values are :keyset, :offset, :full\_read - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the query - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. Valid values are :filter, :error The default value is `:filter`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access [](Ash.html#sum/3) # sum(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1088) Fetches the sum of a given field. [](Ash.html#sum!/3) # sum!(query, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L1110) Fetches the sum of a given field or raises an error. [](Ash.html#update/3) # update(changeset\_or\_record, params\_or\_opts \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2664) ``` @spec update( changeset_or_record :: Ash.Changeset.t() | Ash.Resource.record(), params_or_opts :: map() | Keyword.t(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.record()} | {:ok, Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | {:error, term()} ``` Update a record. - `:params` ([`map/0`](../elixir/typespecs.html#basic-types)) - Parameters to supply, ignored if the input is a changeset, only used when an identifier is given. - `:atomic_upgrade?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true the action will be done atomically if it can (and is configured to do so), ignoring the in memory transformations and validations. You should not generally need to disable this. The default value is `true`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - The domain to use. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the changeset [](Ash.html#update!/3) # update!(changeset\_or\_record, params\_or\_opts \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash.ex#L2638) ``` @spec update!( changeset_or_record :: Ash.Changeset.t() | Ash.Resource.record(), params_or_opts :: map() | Keyword.t(), opts :: Keyword.t() ) :: Ash.Resource.record() | {Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | no_return() ``` Update a record. See [`update/2`](Ash.html#update/2) for more information. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Igniter (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/igniter.ex#L2 "View Source") Codemods and utilities for working with Ash &amp; Igniter # [](Ash.Igniter.html#summary)Summary ## [Functions](Ash.Igniter.html#functions) [codegen(igniter, name)](Ash.Igniter.html#codegen/2) Adds a codegen task, or updates the name to be `<old_name>_and_name` # [](Ash.Igniter.html#functions)Functions [](Ash.Igniter.html#codegen/2) # codegen(igniter, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/igniter.ex#L6) Adds a codegen task, or updates the name to be `<old_name>_and_name` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Mix.Tasks.Helpers (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/helpers.ex#L1 "View Source") Helpers for Ash Mix tasks. # [](Ash.Mix.Tasks.Helpers.html#summary)Summary ## [Functions](Ash.Mix.Tasks.Helpers.html#functions) [domains!(argv)](Ash.Mix.Tasks.Helpers.html#domains!/1) Get all domains for the current project and ensure they are compiled. [extensions!(argv, opts \\\\ \[\])](Ash.Mix.Tasks.Helpers.html#extensions!/2) Gets all extensions in use by the current project's domains and resources # [](Ash.Mix.Tasks.Helpers.html#functions)Functions [](Ash.Mix.Tasks.Helpers.html#domains!/1) # domains!(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/helpers.ex#L102) Get all domains for the current project and ensure they are compiled. [](Ash.Mix.Tasks.Helpers.html#extensions!/2) # extensions!(argv, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/helpers.ex#L11) Gets all extensions in use by the current project's domains and resources [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Notifier behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/notifier.ex#L1 "View Source") A notifier is an extension that receives various events # [](Ash.Notifier.html#summary)Summary ## [Callbacks](Ash.Notifier.html#callbacks) [notify(t)](Ash.Notifier.html#c:notify/1) [requires\_original\_data?(t, action)](Ash.Notifier.html#c:requires_original_data?/2) ## [Functions](Ash.Notifier.html#functions) [notify(resource\_notifications)](Ash.Notifier.html#notify/1) Sends any notifications that can be sent, and returns the rest. # [](Ash.Notifier.html#callbacks)Callbacks [](Ash.Notifier.html#c:notify/1) # notify(t) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/notifier.ex#L5) ``` @callback notify(Ash.Notifier.Notification.t()) :: :ok ``` [](Ash.Notifier.html#c:requires_original_data?/2) # requires\_original\_data?(t, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/notifier.ex#L6) ``` @callback requires_original_data?(Ash.Resource.t(), Ash.Resource.Actions.action()) :: boolean() ``` # [](Ash.Notifier.html#functions)Functions [](Ash.Notifier.html#notify/1) # notify(resource\_notifications) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/notifier.ex#L26) ``` @spec notify([Ash.Notifier.Notification.t()] | Ash.Notifier.Notification.t()) :: [ Ash.Notifier.Notification.t() ] ``` Sends any notifications that can be sent, and returns the rest. A notification can only be sent if you are not currently in a transaction for the resource in question. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Notifier.Notification (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/notification.ex#L1 "View Source") Represents a notification that will be handled by a resource's notifiers Set the `for` key to a notifier or a list of notifiers to route the notification to them. This allows you to produce notifications inside of a `change` module and target specific notifiers with them. `metadata` is freeform data to be set however you want. `resource`, `action`, `data`, `changeset` and `actor` are all set by default based on the details of the action, so they can be omitted. When creating a notification, a resource is required to ensure that the notification isn't sent until the current transaction for that resource is closed. If you don't need this behavior you can explicitly supply `nil` for the resource. If you supply `nil` for the resource, however, you must manually set the `for` option, e.g: `for: Notifier` or `for: [Notifier1, Notifier2]` # [](Ash.Notifier.Notification.html#summary)Summary ## [Types](Ash.Notifier.Notification.html#types) [t()](Ash.Notifier.Notification.html#t:t/0) ## [Functions](Ash.Notifier.Notification.html#functions) [new(resource, opts)](Ash.Notifier.Notification.html#new/2) # [](Ash.Notifier.Notification.html#types)Types [](Ash.Notifier.Notification.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/notification.ex#L20) ``` @type t() :: %Ash.Notifier.Notification{ action: term(), actor: term(), changeset: term(), data: term(), domain: term(), for: term(), from: term(), metadata: term(), resource: term() } ``` # [](Ash.Notifier.Notification.html#functions)Functions [](Ash.Notifier.Notification.html#new/2) # new(resource, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/notification.ex#L22) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Notifier.PubSub (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/pub_sub.ex#L1 "View Source") A builtin notifier to help you publish events over any kind of pub-sub tooling. This is plug and play with `Phoenix.PubSub`, but could be used with any pubsub system. You configure a module that defines a `broadcast/3` function, and then add some "publications" which configure under what conditions an event should be sent and what the topic should be. ## [](Ash.Notifier.PubSub.html#module-example)Example ``` defmodule MyApp.User do use Ash.Resource, # ... notifiers: [Ash.Notifier.PubSub] # ... pub_sub do module MyAppWeb.Endpoint prefix "user" publish :update, ["updated", :_pkey] end end ``` ## [](Ash.Notifier.PubSub.html#module-debugging-pubsub)Debugging PubSub It can be quite frustrating when setting up pub\_sub when everything appears to be set up properly, but you aren't receiving events. This usually means some kind of mismatch between the event names produced by the resource/config of your publications, and you can use the following flag to display debug information about all pub sub events. ``` config :ash, :pub_sub, debug?: true ``` ## [](Ash.Notifier.PubSub.html#module-topic-templates)Topic Templates Often you want to include some piece of data in the thing being changed, like the `:id` attribute. This is done by providing a list as the topic, and using atoms which will be replaced by their corresponding values. They will ultimately be joined with `:`. For example: ``` prefix "user" publish :create, ["created", :user_id] ``` This might publish a message to "user:created:1" for example. For updates, if the field in the template is being changed, a message is sent to *both* values. So if you change `user 1` to `user 2`, the same message would be published to `user:updated:1` and `user:updated:2`. If there are multiple attributes in the template, and they are all being changed, a message is sent for every combination of substitutions. ## [](Ash.Notifier.PubSub.html#module-important)Important If the previous value was `nil` or the field was not selected on the data passed into the action, then a notification is not sent for the previous value. If the new value is `nil` then a notification is not sent for the new value. ## [](Ash.Notifier.PubSub.html#module-template-parts)Template parts Templates may contain lists, in which case all combinations of values in the list will be used. Add `nil` to the list if you want to produce a pattern where that entry is omitted. The atom `:_tenant` may be used. If the changeset has a tenant set on it, that value will be used, otherwise that combination of values is ignored. The atom `:_pkey` may be used. It will be a stringified, concatenation of the primary key fields, or just the primary key if there is only one primary key field. The atom `nil` may be used. It only makes sense to use it in the context of a list of alternatives, and adds a pattern where that part is skipped. ``` publish :updated, [[:team_id, :_tenant], "updated", [:id, nil]] ``` Would produce the following messages, given a `team_id` of 1, a `tenant` of `org_1`, and an `id` of `50`: ``` "1:updated:50" "1:updated" "org_1:updated:50" "org_1:updated" ``` ## [](Ash.Notifier.PubSub.html#module-custom-delimiters)Custom Delimiters It's possible to change the default delimiter used when generating topics. This is useful when working with message brokers like RabbitMQ, which rely on a different set of delimiters for routing. ``` pub_sub do delimiter "." end ``` ## [](Ash.Notifier.PubSub.html#module-named-pubsub-modules)Named Pubsub modules If you are using a phoenix `Endpoint` module for pubsub then this is unnecessary. If you want to use a custom pub sub started with something like `{Phoenix.PubSub, name: MyName}`, then you can provide `MyName` to here. ## [](Ash.Notifier.PubSub.html#module-broadcast-types)Broadcast Types Configured with `broadcast_type`. - `:notification` just sends the notification - `:phoenix_broadcast` sends a `%Phoenix.Socket.Broadcast{}` (see above) - `:broadcast` sends `%{topic: (topic), event: (event), notification: (notification)}` # [](Ash.Notifier.PubSub.html#summary)Summary ## [Functions](Ash.Notifier.PubSub.html#functions) [pub\_sub(body)](Ash.Notifier.PubSub.html#pub_sub/1) [to\_payload(topic, event, notification)](Ash.Notifier.PubSub.html#to_payload/3) # [](Ash.Notifier.PubSub.html#functions)Functions [](Ash.Notifier.PubSub.html#pub_sub/1) # pub\_sub(body) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/pub_sub.ex#L204) [](Ash.Notifier.PubSub.html#to_payload/3) # to\_payload(topic, event, notification) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/pub_sub.ex#L284) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Notifier.PubSub.Info (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/info.ex#L1 "View Source") Introspection helpers for Ash.Notifier.PubSub # [](Ash.Notifier.PubSub.Info.html#summary)Summary ## [Functions](Ash.Notifier.PubSub.Info.html#functions) [broadcast\_type(resource)](Ash.Notifier.PubSub.Info.html#broadcast_type/1) The broadcast type for a resource [delimiter(resource)](Ash.Notifier.PubSub.Info.html#delimiter/1) The delimiter to use when generating message topics [module(resource)](Ash.Notifier.PubSub.Info.html#module/1) The pubsub module for a resource [name(resource)](Ash.Notifier.PubSub.Info.html#name/1) The pubsub name for a resource [prefix(resource)](Ash.Notifier.PubSub.Info.html#prefix/1) The topic prefix for a resource [publications(resource)](Ash.Notifier.PubSub.Info.html#publications/1) The list of publications for a resource # [](Ash.Notifier.PubSub.Info.html#functions)Functions [](Ash.Notifier.PubSub.Info.html#broadcast_type/1) # broadcast\_type(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/info.ex#L30) The broadcast type for a resource [](Ash.Notifier.PubSub.Info.html#delimiter/1) # delimiter(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/info.ex#L20) The delimiter to use when generating message topics [](Ash.Notifier.PubSub.Info.html#module/1) # module(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/info.ex#L10) The pubsub module for a resource [](Ash.Notifier.PubSub.Info.html#name/1) # name(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/info.ex#L25) The pubsub name for a resource [](Ash.Notifier.PubSub.Info.html#prefix/1) # prefix(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/info.ex#L15) The topic prefix for a resource [](Ash.Notifier.PubSub.Info.html#publications/1) # publications(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/info.ex#L5) The list of publications for a resource [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Notifier.PubSub.Publication (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/publication.ex#L1 "View Source") Represents a configured publication from the pubsub notifier on an Ash.Resource # [](Ash.Notifier.PubSub.Publication.html#summary)Summary ## [Functions](Ash.Notifier.PubSub.Publication.html#functions) [publish\_all\_schema()](Ash.Notifier.PubSub.Publication.html#publish_all_schema/0) [schema()](Ash.Notifier.PubSub.Publication.html#schema/0) # [](Ash.Notifier.PubSub.Publication.html#functions)Functions [](Ash.Notifier.PubSub.Publication.html#publish_all_schema/0) # publish\_all\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/publication.ex#L55) [](Ash.Notifier.PubSub.Publication.html#schema/0) # schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/notifier/pub_sub/publication.ex#L54) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.NotLoaded (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/not_loaded.ex#L1 "View Source") Used when a field hasn't been loaded or selected. # [](Ash.NotLoaded.html#summary)Summary ## [Types](Ash.NotLoaded.html#types) [t()](Ash.NotLoaded.html#t:t/0) # [](Ash.NotLoaded.html#types)Types [](Ash.NotLoaded.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/not_loaded.ex#L5) ``` @type t() :: %Ash.NotLoaded{ field: atom(), type: :relationship | :calculation | :aggregate | :attribute } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.OptionsHelpers (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/options_helpers.ex#L1 "View Source") Helpers for working with nimble options # [](Ash.OptionsHelpers.html#summary)Summary ## [Functions](Ash.OptionsHelpers.html#functions) [ash\_resource()](Ash.OptionsHelpers.html#ash_resource/0) Used to configure Spark to know that the type referenced is an Ash.Resource also using Spark. [ash\_type()](Ash.OptionsHelpers.html#ash_type/0) Specifies Ash types that can be allowed when declaring a type for an attribute, calculation, aggregate, etc. [hide\_all\_except(options, keys)](Ash.OptionsHelpers.html#hide_all_except/2) Used for marking an option as hidden so it doesn't show up as an option with Spark. # [](Ash.OptionsHelpers.html#functions)Functions [](Ash.OptionsHelpers.html#ash_resource/0) # ash\_resource() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/options_helpers.ex#L21) ``` @spec ash_resource() :: {:spark, Ash.Resource} ``` Used to configure Spark to know that the type referenced is an Ash.Resource also using Spark. [](Ash.OptionsHelpers.html#ash_type/0) # ash\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/options_helpers.ex#L11) ``` @spec ash_type() :: {:spark_type, Ash.Type, :builtins, [{String.t(), String.t(), String.t()}]} ``` Specifies Ash types that can be allowed when declaring a type for an attribute, calculation, aggregate, etc. [](Ash.OptionsHelpers.html#hide_all_except/2) # hide\_all\_except(options, keys) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/options_helpers.ex#L30) ``` @spec hide_all_except(Keyword.t(), [atom()]) :: Keyword.t() ``` Used for marking an option as hidden so it doesn't show up as an option with Spark. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Page (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/page.ex#L1 "View Source") Types for Ash pages # [](Ash.Page.html#summary)Summary ## [Types](Ash.Page.html#types) [page()](Ash.Page.html#t:page/0) [type()](Ash.Page.html#t:type/0) # [](Ash.Page.html#types)Types [](Ash.Page.html#t:page/0) # page() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/page.ex#L3) ``` @type page() :: Ash.Page.Keyset.t() | Ash.Page.Offset.t() ``` [](Ash.Page.html#t:type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/page.ex#L5) ``` @type type() :: :offset | :keyset ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Page.Keyset (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L1 "View Source") A page of results from `keyset` based pagination. The results are generated with a `keyset` metadata, which can be used to fetch the next/previous pages. # [](Ash.Page.Keyset.html#summary)Summary ## [Types](Ash.Page.Keyset.html#types) [page\_opts()](Ash.Page.Keyset.html#t:page_opts/0) [page\_opts\_opts()](Ash.Page.Keyset.html#t:page_opts_opts/0) [page\_opts\_type()](Ash.Page.Keyset.html#t:page_opts_type/0) [t()](Ash.Page.Keyset.html#t:t/0) ## [Functions](Ash.Page.Keyset.html#functions) [data\_with\_keyset(results, resource, sort)](Ash.Page.Keyset.html#data_with_keyset/3) Appends keyset info to results. [filter(query, values, sort, after\_or\_before)](Ash.Page.Keyset.html#filter/4) Creates filters on the query using the query for the Keyset. [new(results, count, sort, original\_query, more?, opts)](Ash.Page.Keyset.html#new/6) Creates a new `Ash.Page.Keyset.t`. [non\_executable\_binary\_to\_term(binary, opts)](Ash.Page.Keyset.html#non_executable_binary_to_term/2) A restricted version of [`:erlang.binary_to_term/2`](https://www.erlang.org/doc/apps/erts/erlang.html#binary_to_term/2) that forbids *executable* terms, such as anonymous functions. The `opts` are given to the underlying [`:erlang.binary_to_term/2`](https://www.erlang.org/doc/apps/erts/erlang.html#binary_to_term/2) call, with an empty list as a default. By default this function does not restrict atoms, as an atom interned in one node may not yet have been interned on another (except for releases, which preload all code). If you want to avoid atoms from being created, then you can pass `[:safe]` as options, as that will also enable the safety mechanisms from [`:erlang.binary_to_term/2`](https://www.erlang.org/doc/apps/erts/erlang.html#binary_to_term/2) itself. Ripped from [https://github.com/elixir-plug/plug\_crypto/blob/v1.2.0/lib/plug/crypto.ex](https://github.com/elixir-plug/plug_crypto/blob/v1.2.0/lib/plug/crypto.ex) # [](Ash.Page.Keyset.html#types)Types [](Ash.Page.Keyset.html#t:page_opts/0) # page\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L22) ``` @type page_opts() :: [ before: page_opts_opts(), after: page_opts_opts(), limit: page_opts_opts(), filter: page_opts_opts(), count: page_opts_opts() ] ``` [](Ash.Page.Keyset.html#t:page_opts_opts/0) # page\_opts\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L21) ``` @type page_opts_opts() :: [type: page_opts_type(), doc: String.t()] ``` [](Ash.Page.Keyset.html#t:page_opts_type/0) # page\_opts\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L20) ``` @type page_opts_type() :: :non_neg_integer | :pos_integer | :any | :boolean ``` [](Ash.Page.Keyset.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L10) ``` @type t() :: %Ash.Page.Keyset{ after: binary() | nil, before: binary() | nil, count: non_neg_integer(), limit: pos_integer(), more?: boolean(), rerun: {Ash.Query.t(), Keyword.t()}, results: [Ash.Resource.record()] } ``` # [](Ash.Page.Keyset.html#functions)Functions [](Ash.Page.Keyset.html#data_with_keyset/3) # data\_with\_keyset(results, resource, sort) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L94) ``` @spec data_with_keyset([Ash.Resource.record()], term(), term()) :: [ Ash.Resource.record() ] ``` Appends keyset info to results. [](Ash.Page.Keyset.html#filter/4) # filter(query, values, sort, after\_or\_before) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L109) ``` @spec filter(Ash.Query.t(), [term()], term(), :after | :before) :: {:ok, Keyword.t()} | {:error, term()} ``` Creates filters on the query using the query for the Keyset. [](Ash.Page.Keyset.html#new/6) # new(results, count, sort, original\_query, more?, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L78) ``` @spec new( [Ash.Resource.record()], non_neg_integer(), term(), Ash.Query.t(), boolean(), Keyword.t() ) :: t() ``` Creates a new `Ash.Page.Keyset.t`. [](Ash.Page.Keyset.html#non_executable_binary_to_term/2) # non\_executable\_binary\_to\_term(binary, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/keyset.ex#L282) A restricted version of [`:erlang.binary_to_term/2`](https://www.erlang.org/doc/apps/erts/erlang.html#binary_to_term/2) that forbids *executable* terms, such as anonymous functions. The `opts` are given to the underlying [`:erlang.binary_to_term/2`](https://www.erlang.org/doc/apps/erts/erlang.html#binary_to_term/2) call, with an empty list as a default. By default this function does not restrict atoms, as an atom interned in one node may not yet have been interned on another (except for releases, which preload all code). If you want to avoid atoms from being created, then you can pass `[:safe]` as options, as that will also enable the safety mechanisms from [`:erlang.binary_to_term/2`](https://www.erlang.org/doc/apps/erts/erlang.html#binary_to_term/2) itself. Ripped from [https://github.com/elixir-plug/plug\_crypto/blob/v1.2.0/lib/plug/crypto.ex](https://github.com/elixir-plug/plug_crypto/blob/v1.2.0/lib/plug/crypto.ex) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Page.Offset (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/offset.ex#L1 "View Source") A page of results from `offset` based pagination. If a resource supports `keyset` pagination as well, it will also have the `keyset` metadata. # [](Ash.Page.Offset.html#summary)Summary ## [Types](Ash.Page.Offset.html#types) [page\_opts()](Ash.Page.Offset.html#t:page_opts/0) [page\_opts\_opts()](Ash.Page.Offset.html#t:page_opts_opts/0) [page\_opts\_type()](Ash.Page.Offset.html#t:page_opts_type/0) [t()](Ash.Page.Offset.html#t:t/0) ## [Functions](Ash.Page.Offset.html#functions) [new(results, count, original\_query, more?, opts)](Ash.Page.Offset.html#new/5) Creates a new `Ash.Page.Offset.t()`. # [](Ash.Page.Offset.html#types)Types [](Ash.Page.Offset.html#t:page_opts/0) # page\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/offset.ex#L21) ``` @type page_opts() :: [ offset: page_opts_opts(), limit: page_opts_opts(), filter: page_opts_opts(), count: page_opts_opts() ] ``` [](Ash.Page.Offset.html#t:page_opts_opts/0) # page\_opts\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/offset.ex#L20) ``` @type page_opts_opts() :: [type: page_opts_type(), doc: String.t()] ``` [](Ash.Page.Offset.html#t:page_opts_type/0) # page\_opts\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/offset.ex#L19) ``` @type page_opts_type() :: :non_neg_integer | :pos_integer | :any | :boolean ``` [](Ash.Page.Offset.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/offset.ex#L10) ``` @type t() :: %Ash.Page.Offset{ count: integer(), limit: integer(), more?: boolean(), offset: integer(), rerun: {Ash.Query.t(), Keyword.t()}, results: [Ash.Resource.record()] } ``` # [](Ash.Page.Offset.html#functions)Functions [](Ash.Page.Offset.html#new/5) # new(results, count, original\_query, more?, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/page/offset.ex#L71) ``` @spec new( [Ash.Resource.record()], non_neg_integer(), Ash.Query.t(), boolean(), Keyword.t() ) :: t() ``` Creates a new `Ash.Page.Offset.t()`. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.PlugHelpers (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L2 "View Source") Helpers for working with the Plug connection. # [](Ash.PlugHelpers.html#summary)Summary ## [Functions](Ash.PlugHelpers.html#functions) [get\_actor(arg1)](Ash.PlugHelpers.html#get_actor/1) Retrieves the actor from the Plug connection. [get\_context(arg1)](Ash.PlugHelpers.html#get_context/1) Retrieves the context from the Plug connection. [get\_tenant(arg1)](Ash.PlugHelpers.html#get_tenant/1) Retrieves the tenant from the Plug connection. [set\_actor(conn, actor)](Ash.PlugHelpers.html#set_actor/2) Sets the actor inside the Plug connection. [set\_context(conn, context)](Ash.PlugHelpers.html#set_context/2) Sets the context inside the Plug connection. [set\_tenant(conn, tenant)](Ash.PlugHelpers.html#set_tenant/2) Sets the tenant inside the Plug connection. [update\_actor(conn, callback)](Ash.PlugHelpers.html#update_actor/2) Updates the actor inside the Plug connection. [update\_context(conn, callback)](Ash.PlugHelpers.html#update_context/2) Updates the context inside the Plug connection. # [](Ash.PlugHelpers.html#functions)Functions [](Ash.PlugHelpers.html#get_actor/1) # get\_actor(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L77) ``` @spec get_actor(Plug.Conn.t()) :: nil | Ash.Resource.record() ``` Retrieves the actor from the Plug connection. The actor is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#get_actor/1-deprecation-warning)Deprecation warning This function checks to see if the actor is already set in the `@actor` assign, and if so will emit a deprecation warning. This is to allow apps using the previous method a chance to update. Rather than setting the actor in the assigns, please use the [`set_actor/2`](Ash.PlugHelpers.html#set_actor/2) method. ## [](Ash.PlugHelpers.html#get_actor/1-example)Example ``` iex> actor = build_actor(%{email: "marty@1985.retro"}) ...> conn = build_conn() |> put_private(:ash, %{actor: actor}) ...> actor = get_actor(conn) %{email: "marty@1985.retro"} = actor iex> actor = build_actor(%{email: "marty@1985.retro"}) ...> conn = build_conn() |> assign(:actor, actor) ...> actor = get_actor(conn) %{email: "marty@1985.retro"} = actor ``` [](Ash.PlugHelpers.html#get_context/1) # get\_context(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L218) ``` @spec get_context(Plug.Conn.t()) :: nil | map() ``` Retrieves the context from the Plug connection. The context is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#get_context/1-example)Example ``` iex> context = %{fraud_score: 0.427} ...> conn = build_conn() |> put_private(:ash, %{context: context}) ...> context = get_context(conn) %{fraud_score: 0.427} ``` [](Ash.PlugHelpers.html#get_tenant/1) # get\_tenant(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L168) ``` @spec get_tenant(Plug.Conn.t()) :: term() ``` Retrieves the tenant from the Plug connection. The tenant is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#get_tenant/1-deprecation-warning)Deprecation warning This function checks to see if the tenant is already set in the `@tenant` assign, and if so will emit a deprecation warning. This is to allow apps using the previous method a chance to update. Rather than setting the tenant in the assigns, please use the [`set_tenant/2`](Ash.PlugHelpers.html#set_tenant/2) method. ## [](Ash.PlugHelpers.html#get_tenant/1-example)Example ``` iex> conn = build_conn() |> put_private(:ash, %{tenant: "my-tenant"}) ...> tenant = get_tenant(conn) "my_tenant" = tenant iex> conn = build_conn() |> assign(:tenant, "my-tenant") ...> tenant = get_tenant(conn) "my_tenant" = tenant ``` [](Ash.PlugHelpers.html#set_actor/2) # set\_actor(conn, actor) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L38) ``` @spec set_actor(Plug.Conn.t(), Ash.Resource.record()) :: Plug.Conn.t() ``` Sets the actor inside the Plug connection. The actor is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#set_actor/2-example)Example ``` iex> actor = build_actor(%{email: "marty@1985.retro"}) ...> conn = build_conn() |> set_actor(actor) %Plug.Conn{private: %{ash: %{actor: %{email: "marty@1985.retro"}}}} = conn ``` [](Ash.PlugHelpers.html#set_context/2) # set\_context(conn, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L194) ``` @spec set_context(Plug.Conn.t(), map()) :: Plug.Conn.t() ``` Sets the context inside the Plug connection. Context can be used to store abitrary data about the user, connection, or anything else you like that doesn't belong as part of the actor or tenant. The context is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#set_context/2-example)Example ``` iex> context = %{fraud_score: 0.427} ...> conn = build_conn() |> set_context(context) %Plug.Conn{private: %{ash: %{context: %{fraud_score: 0.427}}}} ``` [](Ash.PlugHelpers.html#set_tenant/2) # set\_tenant(conn, tenant) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L130) ``` @spec set_tenant(Plug.Conn.t(), Ash.ToTenant.t()) :: Plug.Conn.t() ``` Sets the tenant inside the Plug connection. The tenant is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#set_tenant/2-example)Example ``` iex> conn = build_conn() |> set_tenant("my-tenant") %Plug.Conn{private: %{ash: %{tenant: "my-tenant}}} = conn ``` [](Ash.PlugHelpers.html#update_actor/2) # update\_actor(conn, callback) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L107) ``` @spec update_actor(Plug.Conn.t(), (nil | Ash.Resource.record() -> nil | Ash.Resource.record())) :: Plug.Conn.t() ``` Updates the actor inside the Plug connection. The actor is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#update_actor/2-example)Example ``` iex> actor = build_actor(%{email: "marty@1985.retro"}) ...> conn = build_conn() |> put_private(:ash, %{actor: actor}) ...> actor = get_actor(conn) %{email: "marty@1985.retro"} = actor ...> conn = update_actor(conn, fn actor -> Map.put(actor, :name, "Marty Retro") end) ...> actor = get_actor(conn) %{email: "marty@1985.retro", name: "Marty Retro"} = actor ...> conn = update_actor(conn, fn actor -> Map.delete(actor, :email) end) ...> actor = get_actor(conn) %{name: "Marty Retro"} = actor ``` [](Ash.PlugHelpers.html#update_context/2) # update\_context(conn, callback) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/plug_helpers.ex#L242) ``` @spec update_context(Plug.Conn.t(), (nil | map() -> nil | map())) :: Plug.Conn.t() ``` Updates the context inside the Plug connection. The context is stored inside the [connection's private fields](https://hexdocs.pm/plug/Plug.Conn.html#module-private-fields). ## [](Ash.PlugHelpers.html#update_context/2-example)Example ``` iex> context = %{species: "Fythetropozoat"} ...> conn = build_conn() |> put_private(:ash, %{context: context}) ...> context = get_context(conn) %{fraud_score: 0.427} ...> conn = update_context(conn, fn context -> Map.put(context, :location, "Barnard's Loop") end) ...> context = get_context(conn) %{species: "Fythetropozoat", location: "Barnard's Loop"} ...> conn = update_context(conn, fn context -> Map.delete(context, :fraud_score) end) ...> context = get_context(conn) %{location: "Barnard's Loop"} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Authorizer (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L1 "View Source") An authorization extension for ash resources. To add this extension to a resource, add it to the list of `authorizers` like so: ``` use Ash.Resource, ..., authorizers: [ Ash.Policy.Authorizer ] ``` A resource can be given a set of policies, which are enforced on each call to a resource action. For reads, policies can be configured to filter out data that the actor shouldn't see, as opposed to resulting in a forbidden error. See the [policies guide](policies.html) for practical examples. Policies are solved/managed via a boolean satisfiability solver. To read more about boolean satisfiability, see this page: [https://en.wikipedia.org/wiki/Boolean\_satisfiability\_problem](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem). At the end of the day, however, it is not necessary to understand exactly how Ash takes your authorization requirements and determines if a request is allowed. The important thing to understand is that Ash may or may not run any/all of your authorization rules as they may be deemed unnecessary. As such, authorization checks should have no side effects. Ideally, the checks built-in to ash should cover the bulk of your needs. # [](Ash.Policy.Authorizer.html#summary)Summary ## [Types](Ash.Policy.Authorizer.html#types) [t()](Ash.Policy.Authorizer.html#t:t/0) ## [Functions](Ash.Policy.Authorizer.html#functions) [alter\_sort(sort, authorizer, context)](Ash.Policy.Authorizer.html#alter_sort/3) [expr\_check(expr)](Ash.Policy.Authorizer.html#expr_check/1) [field\_policies(body)](Ash.Policy.Authorizer.html#field_policies/1) [install(igniter, module, type, path, argv)](Ash.Policy.Authorizer.html#install/5) [policies(body)](Ash.Policy.Authorizer.html#policies/1) [print\_tuple\_boolean(v)](Ash.Policy.Authorizer.html#print_tuple_boolean/1) [template\_var(expr)](Ash.Policy.Authorizer.html#template_var/1) # [](Ash.Policy.Authorizer.html#types)Types [](Ash.Policy.Authorizer.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L23) ``` @type t() :: %Ash.Policy.Authorizer{ action: Ash.Resource.Actions.Action.t(), action_input: Ash.ActionInput.t() | nil, actor: term(), changeset: Ash.Changeset.t() | nil, check_scenarios: [map()], context: map(), data: term(), data_facts: map(), domain: Ash.Domain.t(), facts: map(), for_fields: term(), policies: [term()], query: Ash.Query.t() | nil, real_scenarios: [map()], resource: Ash.Resource.t(), scenarios: [map()], solver_statement: term(), subject: Ash.Query.t() | Ash.Changeset.t() | Ash.ActionInput.t() } ``` # [](Ash.Policy.Authorizer.html#functions)Functions [](Ash.Policy.Authorizer.html#alter_sort/3) # alter\_sort(sort, authorizer, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L748) [](Ash.Policy.Authorizer.html#expr_check/1) # expr\_check(expr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L1835) [](Ash.Policy.Authorizer.html#field_policies/1) # field\_policies(body) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L480) [](Ash.Policy.Authorizer.html#install/5) # install(igniter, module, type, path, argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L533) [](Ash.Policy.Authorizer.html#policies/1) # policies(body) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L480) [](Ash.Policy.Authorizer.html#print_tuple_boolean/1) # print\_tuple\_boolean(v) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L1433) [](Ash.Policy.Authorizer.html#template_var/1) # template\_var(expr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/authorizer.ex#L1839) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/add_missing_field_policies.ex#L1 "View Source") Adds field policies for any missing fields # [](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#summary)Summary ## [Functions](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#functions) [after?(arg1)](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl)](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#functions)Functions [](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#after?/1) # after?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/add_missing_field_policies.ex#L8) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/add_missing_field_policies.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/add_missing_field_policies.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Policy.Authorizer.Transformers.AddMissingFieldPolicies.html#transform/1) # transform(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/add_missing_field_policies.ex#L11) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Authorizer.Transformers.CacheFieldPolicies (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/cache_field_policies.ex#L1 "View Source") Cache field policies for each field # [](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#summary)Summary ## [Functions](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#functions) [after?(\_)](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl)](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#functions)Functions [](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/cache_field_policies.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/cache_field_policies.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/cache_field_policies.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Policy.Authorizer.Transformers.CacheFieldPolicies.html#transform/1) # transform(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/authorizer/transformers/cache_field_policies.ex#L8) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Chart.Mermaid (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/chart/mermaid.ex#L1 "View Source") Generates policy mermaid charts # [](Ash.Policy.Chart.Mermaid.html#summary)Summary ## [Functions](Ash.Policy.Chart.Mermaid.html#functions) [chart(resource)](Ash.Policy.Chart.Mermaid.html#chart/1) # [](Ash.Policy.Chart.Mermaid.html#functions)Functions [](Ash.Policy.Chart.Mermaid.html#chart/1) # chart(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/chart/mermaid.ex#L4) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.AccessingFrom (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/accessing_from.ex#L1 "View Source") This check is true when the current action is being run "through" a relationship. # [](Ash.Policy.Check.AccessingFrom.html#summary)Summary ## [Functions](Ash.Policy.Check.AccessingFrom.html#functions) [eager\_evaluate?()](Ash.Policy.Check.AccessingFrom.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.AccessingFrom.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.AccessingFrom.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.AccessingFrom.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.AccessingFrom.html#functions)Functions [](Ash.Policy.Check.AccessingFrom.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/accessing_from.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.AccessingFrom.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/accessing_from.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.AccessingFrom.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/accessing_from.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.AccessingFrom.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/accessing_from.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Action (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action.ex#L1 "View Source") This check is true when the action name matches the provided action name. # [](Ash.Policy.Check.Action.html#summary)Summary ## [Functions](Ash.Policy.Check.Action.html#functions) [eager\_evaluate?()](Ash.Policy.Check.Action.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.Action.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.Action.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.Action.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.Action.html#functions)Functions [](Ash.Policy.Check.Action.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.Action.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.Action.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.Action.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.ActionType (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action_type.ex#L1 "View Source") This check is true when the action type matches the provided type # [](Ash.Policy.Check.ActionType.html#summary)Summary ## [Functions](Ash.Policy.Check.ActionType.html#functions) [eager\_evaluate?()](Ash.Policy.Check.ActionType.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.ActionType.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.ActionType.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.ActionType.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.ActionType.html#functions)Functions [](Ash.Policy.Check.ActionType.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action_type.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.ActionType.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action_type.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.ActionType.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action_type.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.ActionType.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/action_type.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.ActorAbsent (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_absent.ex#L1 "View Source") This check is true when the actor is `nil`, and false when the actor is specified. # [](Ash.Policy.Check.ActorAbsent.html#summary)Summary ## [Functions](Ash.Policy.Check.ActorAbsent.html#functions) [eager\_evaluate?()](Ash.Policy.Check.ActorAbsent.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.ActorAbsent.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.ActorAbsent.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.ActorAbsent.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.ActorAbsent.html#functions)Functions [](Ash.Policy.Check.ActorAbsent.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_absent.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.ActorAbsent.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_absent.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.ActorAbsent.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_absent.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.ActorAbsent.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_absent.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.ActorAttributeEquals (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_attribute_equals.ex#L1 "View Source") This check is true when the value of the specified attribute of the actor equals the specified value. # [](Ash.Policy.Check.ActorAttributeEquals.html#summary)Summary ## [Functions](Ash.Policy.Check.ActorAttributeEquals.html#functions) [eager\_evaluate?()](Ash.Policy.Check.ActorAttributeEquals.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.ActorAttributeEquals.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.ActorAttributeEquals.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.ActorAttributeEquals.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.ActorAttributeEquals.html#functions)Functions [](Ash.Policy.Check.ActorAttributeEquals.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_attribute_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.ActorAttributeEquals.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_attribute_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.ActorAttributeEquals.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_attribute_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.ActorAttributeEquals.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_attribute_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.ActorPresent (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_present.ex#L1 "View Source") This check is true when there is an actor specified, and false when the actor is `nil`. # [](Ash.Policy.Check.ActorPresent.html#summary)Summary ## [Functions](Ash.Policy.Check.ActorPresent.html#functions) [eager\_evaluate?()](Ash.Policy.Check.ActorPresent.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.ActorPresent.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.ActorPresent.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.ActorPresent.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.ActorPresent.html#functions)Functions [](Ash.Policy.Check.ActorPresent.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_present.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.ActorPresent.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_present.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.ActorPresent.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_present.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.ActorPresent.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/actor_present.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Builtins (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L1 "View Source") The global authorization checks built into ash # [](Ash.Policy.Check.Builtins.html#summary)Summary ## [Functions](Ash.Policy.Check.Builtins.html#functions) [accessing\_from(resource, relationship)](Ash.Policy.Check.Builtins.html#accessing_from/2) This check is true when the current action is being run "through" a relationship. [action(action)](Ash.Policy.Check.Builtins.html#action/1) This check is true when the action name matches the provided action name or names. [action\_type(action\_type)](Ash.Policy.Check.Builtins.html#action_type/1) This check is true when the action type matches the provided type [actor\_absent()](Ash.Policy.Check.Builtins.html#actor_absent/0) This check is false when there is an actor specified, and true when the actor is `nil`. [actor\_attribute\_equals(attribute, value)](Ash.Policy.Check.Builtins.html#actor_attribute_equals/2) This check is true when the value of the specified attribute of the actor equals the specified value. [actor\_present()](Ash.Policy.Check.Builtins.html#actor_present/0) This check is true when there is an actor specified, and false when the actor is `nil`. [always()](Ash.Policy.Check.Builtins.html#always/0) This check always passes. [changing\_attributes(opts)](Ash.Policy.Check.Builtins.html#changing_attributes/1) This check is true when attribute changes correspond to the provided options. [changing\_relationship(relationship)](Ash.Policy.Check.Builtins.html#changing_relationship/1) This check is true when the specified relationship is changing [changing\_relationships(relationships)](Ash.Policy.Check.Builtins.html#changing_relationships/1) This check is true when the specified relationships are changing [context\_equals(key, value)](Ash.Policy.Check.Builtins.html#context_equals/2) This check is true when the value of the specified key or path in the changeset or query context equals the specified value. [filtering\_on(path \\\\ \[\], field)](Ash.Policy.Check.Builtins.html#filtering_on/2) deprecated This check is true when the field provided is being referenced anywhere in a filter statement. [just\_created\_with\_action(action\_name)](Ash.Policy.Check.Builtins.html#just_created_with_action/1) [loading(field)](Ash.Policy.Check.Builtins.html#loading/1) This check is true when the field or relationship, or path to field, is being loaded and false when it is not. [matches(description, func)](Ash.Policy.Check.Builtins.html#matches/2) This check is true when the specified function returns true [never()](Ash.Policy.Check.Builtins.html#never/0) This check never passes. [relates\_to\_actor\_via(relationship\_path, opts \\\\ \[\])](Ash.Policy.Check.Builtins.html#relates_to_actor_via/2) This check passes if the data relates to the actor via the specified relationship or path of relationships. [relating\_to\_actor(relationship)](Ash.Policy.Check.Builtins.html#relating_to_actor/1) This check is true when the specified relationship is being changed to the current actor. [resource(resource)](Ash.Policy.Check.Builtins.html#resource/1) This check is true when the resource name matches the provided resource name or names. [selecting(attribute)](Ash.Policy.Check.Builtins.html#selecting/1) This check is true when the field is being selected and false when it is not. # [](Ash.Policy.Check.Builtins.html#functions)Functions [](Ash.Policy.Check.Builtins.html#accessing_from/2) # accessing\_from(resource, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L189) ``` @spec accessing_from(Ash.Resource.t(), atom()) :: Ash.Policy.Check.ref() ``` This check is true when the current action is being run "through" a relationship. Cases where this happens: 1. Loading related data 2. Managing relationships 3. Aggregating data 4. Filtering on relationships [](Ash.Policy.Check.Builtins.html#action/1) # action(action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L70) ``` @spec action(atom() | [atom()]) :: Ash.Policy.Check.ref() ``` This check is true when the action name matches the provided action name or names. This is a very common pattern, allowing action-specific policies. [](Ash.Policy.Check.Builtins.html#action_type/1) # action\_type(action\_type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L49) ``` @spec action_type(Ash.Resource.Actions.action_type()) :: Ash.Policy.Check.ref() ``` This check is true when the action type matches the provided type This is useful for writing policies that apply to all actions of a given type. For example: ``` policy action_type(:read) do authorize_if relates_to_actor_via(:owner) end ``` [](Ash.Policy.Check.Builtins.html#actor_absent/0) # actor\_absent() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L94) ``` @spec actor_absent() :: Ash.Policy.Check.ref() ``` This check is false when there is an actor specified, and true when the actor is `nil`. [](Ash.Policy.Check.Builtins.html#actor_attribute_equals/2) # actor\_attribute\_equals(attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L232) ``` @spec actor_attribute_equals(atom(), any()) :: Ash.Policy.Check.ref() ``` This check is true when the value of the specified attribute of the actor equals the specified value. This check will *never* pass if the actor does not have the specified key. For example, `actor_attribute_equals(:missing_key, nil)` [](Ash.Policy.Check.Builtins.html#actor_present/0) # actor\_present() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L86) ``` @spec actor_present() :: Ash.Policy.Check.ref() ``` This check is true when there is an actor specified, and false when the actor is `nil`. [](Ash.Policy.Check.Builtins.html#always/0) # always() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L20) ``` @spec always() :: Ash.Policy.Check.ref() ``` This check always passes. Can be useful for "deny-list" style authorization. For example: ``` policy action_type(:read) do forbid_if actor_attribute_equals(:disabled, true) forbid_if actor_attribute_equals(:active, false) authorize_if always() end ``` Without that last clause, the policy would never pass. [](Ash.Policy.Check.Builtins.html#changing_attributes/1) # changing\_attributes(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L278) This check is true when attribute changes correspond to the provided options. Provide a keyword list of options or just an atom representing the attribute. For example: ``` # if you are changing both first name and last name changing_attributes([:first_name, :last_name]) # if you are changing first name to fred changing_attributes(first_name: [to: "fred"]) # if you are changing last name from bob changing_attributes(last_name: [from: "bob"]) # if you are changing :first_name at all, last_name from "bob" and middle name from "tom" to "george" changing_attributes([:first_name, last_name: [from: "bob"], middle_name: [from: "tom", to: "george]]) ``` [](Ash.Policy.Check.Builtins.html#changing_relationship/1) # changing\_relationship(relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L304) This check is true when the specified relationship is changing [](Ash.Policy.Check.Builtins.html#changing_relationships/1) # changing\_relationships(relationships) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L309) This check is true when the specified relationships are changing [](Ash.Policy.Check.Builtins.html#context_equals/2) # context\_equals(key, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L253) This check is true when the value of the specified key or path in the changeset or query context equals the specified value. Note that the context is not shared with other queries (e.g. loads). For example: ``` # Given this check on Profile authorize_if context_equals(:allow_this?, true) # This load will not have the context and will not be authorized Ash.load!(user, :profile, context: %{allow_this?: true}) # But this will have the context and will be authorized Ash.load!(user, [profile: Ash.Query.set_context(Profile, %{allow_this?: true})]) ``` [](Ash.Policy.Check.Builtins.html#filtering_on/2) # filtering\_on(path \\\\ \[], field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L135) This function is deprecated. \`filtering\_on/2\` check is deprecated. Instead, add arguments and add policies that said arguments are set. For complex queries, policies on what is being filtered on require multiple authorization passes of the same resource, leading to a large amount of typically unnecessary complexity. Additionally, they could yield false negatives in some scenarios, and more work would be needed to ensure that they don't. . ``` @spec filtering_on(atom() | [atom()], atom()) :: Ash.Policy.Check.ref() ``` This check is true when the field provided is being referenced anywhere in a filter statement. This applies to related filters as well. For example: ``` policy actor_attribute_equals(:is_admin, false) do forbid_if filtering_on(:email) # a path can be provided as well forbid_if filtering_on([:owner], :email) end ``` The first will return true in situations like: ``` Ash.Query.filter(User, email == "blah") Ash.Query.filter(Tweet, author.email == "blah") ``` The second will return true on queries like: ``` Ash.Query.filter(Post, owner.email == "blah") Ash.Query.filter(Comment, post.owner.email == "blah") ``` [](Ash.Policy.Check.Builtins.html#just_created_with_action/1) # just\_created\_with\_action(action\_name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L60) ``` @spec just_created_with_action(atom()) :: Ash.Policy.Check.ref() ``` [](Ash.Policy.Check.Builtins.html#loading/1) # loading(field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L174) ``` @spec loading(atom()) :: Ash.Policy.Check.ref() ``` This check is true when the field or relationship, or path to field, is being loaded and false when it is not. This is always false for `create`/`update`/`destroy` actions, because you cannot load fields on those action types. [](Ash.Policy.Check.Builtins.html#matches/2) # matches(description, func) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L314) This check is true when the specified function returns true [](Ash.Policy.Check.Builtins.html#never/0) # never() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L31) ``` @spec never() :: Ash.Policy.Check.ref() ``` This check never passes. There is, generally speaking, no reason to use this, but it exists for completeness sake. [](Ash.Policy.Check.Builtins.html#relates_to_actor_via/2) # relates\_to\_actor\_via(relationship\_path, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L216) ``` @spec relates_to_actor_via( atom(), keyword() ) :: Ash.Policy.Check.ref() ``` This check passes if the data relates to the actor via the specified relationship or path of relationships. For `update` &amp; `destroy` actions, this check will apply to *the original data* before the changes are applied. For `create` actions this check is very unlikely to pass. This is because relationships are modified *after* authorization happens, not before. For example: ``` policy action_type(:read) do authorize_if relates_to_actor_via(:owner) # Path of relationships: authorize_if relates_to_actor_via([:account, :user]) # When the resource relates to a field of the actor: authorize_if relates_to_actor_via(:roles, field: :role) end ``` [](Ash.Policy.Check.Builtins.html#relating_to_actor/1) # relating\_to\_actor(relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L299) This check is true when the specified relationship is being changed to the current actor. This only supports `belongs_to` relationships at the moment, and will detect two cases: 1. the `source_attribute` is being changed directly 2. the relationship is being changed with `on_lookup?: :relate`, and a single input is being provided. [](Ash.Policy.Check.Builtins.html#resource/1) # resource(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L78) ``` @spec resource(atom() | [atom()]) :: Ash.Policy.Check.ref() ``` This check is true when the resource name matches the provided resource name or names. [](Ash.Policy.Check.Builtins.html#selecting/1) # selecting(attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/built_in_checks.ex#L164) ``` @spec selecting(atom()) :: Ash.Policy.Check.ref() ``` This check is true when the field is being selected and false when it is not. This won't affect filters placed on this resource, so you may also want to either: - Mark the given field as `filterable? false` - Add another check for `filtering_on(:field)` For example: ``` policy action_type(:read) do # The actor can read and filter on their own email authorize_if expr(id == ^actor(:id)) # No one else can select or filter on their email forbid_if selecting(:email) forbid_if filtering_on(:email) # Otherwise, the policy passes authorize_if always() end ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.ChangingAttributes (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L1 "View Source") This check is true when attribute changes correspond to the provided options. # [](Ash.Policy.Check.ChangingAttributes.html#summary)Summary ## [Functions](Ash.Policy.Check.ChangingAttributes.html#functions) [auto\_filter(actor, authorizer, opts)](Ash.Policy.Check.ChangingAttributes.html#auto_filter/3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [auto\_filter\_not(actor, authorizer, opts)](Ash.Policy.Check.ChangingAttributes.html#auto_filter_not/3) [check(actor, data, authorizer, opts)](Ash.Policy.Check.ChangingAttributes.html#check/4) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [eager\_evaluate?()](Ash.Policy.Check.ChangingAttributes.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [expand\_description(actor, authorizer, opts)](Ash.Policy.Check.ChangingAttributes.html#expand_description/3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [prefer\_expanded\_description?()](Ash.Policy.Check.ChangingAttributes.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [reject(actor, authorizer, opts)](Ash.Policy.Check.ChangingAttributes.html#reject/3) Callback implementation for [`Ash.Policy.FilterCheck.reject/3`](Ash.Policy.FilterCheck.html#c:reject/3). [requires\_original\_data?(\_, \_)](Ash.Policy.Check.ChangingAttributes.html#requires_original_data?/2) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [strict\_check(actor, authorizer, opts)](Ash.Policy.Check.ChangingAttributes.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [strict\_check\_context(opts)](Ash.Policy.Check.ChangingAttributes.html#strict_check_context/1) [type()](Ash.Policy.Check.ChangingAttributes.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.ChangingAttributes.html#functions)Functions [](Ash.Policy.Check.ChangingAttributes.html#auto_filter/3) # auto\_filter(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [](Ash.Policy.Check.ChangingAttributes.html#auto_filter_not/3) # auto\_filter\_not(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) [](Ash.Policy.Check.ChangingAttributes.html#check/4) # check(actor, data, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [](Ash.Policy.Check.ChangingAttributes.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.ChangingAttributes.html#expand_description/3) # expand\_description(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [](Ash.Policy.Check.ChangingAttributes.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.ChangingAttributes.html#reject/3) # reject(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.FilterCheck.reject/3`](Ash.Policy.FilterCheck.html#c:reject/3). [](Ash.Policy.Check.ChangingAttributes.html#requires_original_data?/2) # requires\_original\_data?(\_, \_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [](Ash.Policy.Check.ChangingAttributes.html#strict_check/3) # strict\_check(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.ChangingAttributes.html#strict_check_context/1) # strict\_check\_context(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) [](Ash.Policy.Check.ChangingAttributes.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_attributes.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.ChangingRelationships (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_relationships.ex#L1 "View Source") This check is true when the specified relationship is changing # [](Ash.Policy.Check.ChangingRelationships.html#summary)Summary ## [Functions](Ash.Policy.Check.ChangingRelationships.html#functions) [eager\_evaluate?()](Ash.Policy.Check.ChangingRelationships.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.ChangingRelationships.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.ChangingRelationships.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.ChangingRelationships.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.ChangingRelationships.html#functions)Functions [](Ash.Policy.Check.ChangingRelationships.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_relationships.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.ChangingRelationships.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_relationships.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.ChangingRelationships.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_relationships.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.ChangingRelationships.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/changing_relationships.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.ContextEquals (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/context_equals.ex#L1 "View Source") This check is true when the value of the specified key or path in the changeset or query context equals the specified value. # [](Ash.Policy.Check.ContextEquals.html#summary)Summary ## [Functions](Ash.Policy.Check.ContextEquals.html#functions) [eager\_evaluate?()](Ash.Policy.Check.ContextEquals.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.ContextEquals.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.ContextEquals.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.ContextEquals.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.ContextEquals.html#functions)Functions [](Ash.Policy.Check.ContextEquals.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/context_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.ContextEquals.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/context_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.ContextEquals.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/context_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.ContextEquals.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/context_equals.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Expression (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L1 "View Source") The check module used for `expr`s in policies # [](Ash.Policy.Check.Expression.html#summary)Summary ## [Functions](Ash.Policy.Check.Expression.html#functions) [auto\_filter(actor, authorizer, opts)](Ash.Policy.Check.Expression.html#auto_filter/3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [auto\_filter\_not(actor, authorizer, opts)](Ash.Policy.Check.Expression.html#auto_filter_not/3) [check(actor, data, authorizer, opts)](Ash.Policy.Check.Expression.html#check/4) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [eager\_evaluate?()](Ash.Policy.Check.Expression.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [expand\_description(actor, authorizer, opts)](Ash.Policy.Check.Expression.html#expand_description/3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [reject(actor, authorizer, opts)](Ash.Policy.Check.Expression.html#reject/3) Callback implementation for [`Ash.Policy.FilterCheck.reject/3`](Ash.Policy.FilterCheck.html#c:reject/3). [requires\_original\_data?(\_, \_)](Ash.Policy.Check.Expression.html#requires_original_data?/2) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [strict\_check(actor, authorizer, opts)](Ash.Policy.Check.Expression.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [strict\_check\_context(opts)](Ash.Policy.Check.Expression.html#strict_check_context/1) [type()](Ash.Policy.Check.Expression.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.Expression.html#functions)Functions [](Ash.Policy.Check.Expression.html#auto_filter/3) # auto\_filter(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [](Ash.Policy.Check.Expression.html#auto_filter_not/3) # auto\_filter\_not(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) [](Ash.Policy.Check.Expression.html#check/4) # check(actor, data, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [](Ash.Policy.Check.Expression.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.Expression.html#expand_description/3) # expand\_description(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [](Ash.Policy.Check.Expression.html#reject/3) # reject(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.FilterCheck.reject/3`](Ash.Policy.FilterCheck.html#c:reject/3). [](Ash.Policy.Check.Expression.html#requires_original_data?/2) # requires\_original\_data?(\_, \_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [](Ash.Policy.Check.Expression.html#strict_check/3) # strict\_check(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.Expression.html#strict_check_context/1) # strict\_check\_context(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) [](Ash.Policy.Check.Expression.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/expression.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.FilteringOn (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/filtering_on.ex#L1 "View Source") This check is true when the field provided is being referenced anywhere in a filter statement. # [](Ash.Policy.Check.FilteringOn.html#summary)Summary ## [Functions](Ash.Policy.Check.FilteringOn.html#functions) [eager\_evaluate?()](Ash.Policy.Check.FilteringOn.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.FilteringOn.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.FilteringOn.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.FilteringOn.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.FilteringOn.html#functions)Functions [](Ash.Policy.Check.FilteringOn.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/filtering_on.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.FilteringOn.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/filtering_on.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.FilteringOn.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/filtering_on.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.FilteringOn.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/filtering_on.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L1 "View Source") A behaviour for declaring checks, which can be used to easily construct authorization rules. If a check can be expressed simply, i.e as a function of the actor, or the context of the request, see [`Ash.Policy.SimpleCheck`](Ash.Policy.SimpleCheck.html) for an easy way to write that check. If a check can be expressed with a filter statement, see [`Ash.Policy.FilterCheck`](Ash.Policy.FilterCheck.html) for an easy way to write that check. # [](Ash.Policy.Check.html#summary)Summary ## [Types](Ash.Policy.Check.html#types) [actor()](Ash.Policy.Check.html#t:actor/0) [authorizer()](Ash.Policy.Check.html#t:authorizer/0) [check\_type()](Ash.Policy.Check.html#t:check_type/0) [options()](Ash.Policy.Check.html#t:options/0) [ref()](Ash.Policy.Check.html#t:ref/0) [t()](Ash.Policy.Check.html#t:t/0) ## [Callbacks](Ash.Policy.Check.html#callbacks) [auto\_filter(actor, authorizer, options)](Ash.Policy.Check.html#c:auto_filter/3) An optional callback, that allows the check to work with policies set to `access_type :filter` [check(actor, list, map, options)](Ash.Policy.Check.html#c:check/4) An optional callback, hat allows the check to work with policies set to `access_type :runtime` [describe(options)](Ash.Policy.Check.html#c:describe/1) Describe the check in human readable format, given the options [eager\_evaluate?()](Ash.Policy.Check.html#c:eager_evaluate?/0) [expand\_description(actor, authorizer, options)](Ash.Policy.Check.html#c:expand_description/3) Expands the description of the check, given the actor and subject [prefer\_expanded\_description?()](Ash.Policy.Check.html#c:prefer_expanded_description?/0) Whether or not the expanded description should replace the basic description in breakdowns [requires\_original\_data?(actor, options)](Ash.Policy.Check.html#c:requires_original_data?/2) Whether or not your check requires the original data of a changeset (if applicable) [strict\_check(actor, authorizer, options)](Ash.Policy.Check.html#c:strict_check/3) Strict checks should be cheap, and should never result in external calls (like database or domain) [type()](Ash.Policy.Check.html#c:type/0) The type of the check ## [Functions](Ash.Policy.Check.html#functions) [defines\_auto\_filter?(module)](Ash.Policy.Check.html#defines_auto_filter?/1) [defines\_check?(module)](Ash.Policy.Check.html#defines_check?/1) # [](Ash.Policy.Check.html#types)Types [](Ash.Policy.Check.html#t:actor/0) # actor() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L12) ``` @type actor() :: any() ``` [](Ash.Policy.Check.html#t:authorizer/0) # authorizer() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L14) ``` @type authorizer() :: Ash.Policy.Authorizer.t() ``` [](Ash.Policy.Check.html#t:check_type/0) # check\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L15) ``` @type check_type() :: :simple | :filter | :manual ``` [](Ash.Policy.Check.html#t:options/0) # options() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L13) ``` @type options() :: Keyword.t() ``` [](Ash.Policy.Check.html#t:ref/0) # ref() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L16) ``` @type ref() :: {module(), Keyword.t()} | module() ``` [](Ash.Policy.Check.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L25) ``` @type t() :: %Ash.Policy.Check{ check: term(), check_module: term(), check_opts: term(), type: term() } ``` # [](Ash.Policy.Check.html#callbacks)Callbacks [](Ash.Policy.Check.html#c:auto_filter/3) # auto\_filter(actor, authorizer, options) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L40) ``` @callback auto_filter(actor(), authorizer(), options()) :: Keyword.t() | Ash.Expr.t() ``` An optional callback, that allows the check to work with policies set to `access_type :filter` Return a keyword list filter that will be applied to the query being made, and will scope the results to match the rule [](Ash.Policy.Check.html#c:check/4) # check(actor, list, map, options) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L46) ``` @callback check(actor(), [Ash.Resource.record()], map(), options()) :: [ Ash.Resource.record() ] ``` An optional callback, hat allows the check to work with policies set to `access_type :runtime` Takes a list of records, and returns the subset of authorized records. [](Ash.Policy.Check.html#c:describe/1) # describe(options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L49) ``` @callback describe(options()) :: String.t() ``` Describe the check in human readable format, given the options [](Ash.Policy.Check.html#c:eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L72) ``` @callback eager_evaluate?() :: boolean() ``` [](Ash.Policy.Check.html#c:expand_description/3) # expand\_description(actor, authorizer, options) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L52) ``` @callback expand_description( actor(), authorizer(), options() ) :: {:ok, String.t()} | :none ``` Expands the description of the check, given the actor and subject [](Ash.Policy.Check.html#c:prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L59) ``` @callback prefer_expanded_description?() :: boolean() ``` Whether or not the expanded description should replace the basic description in breakdowns [](Ash.Policy.Check.html#c:requires_original_data?/2) # requires\_original\_data?(actor, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L62) ``` @callback requires_original_data?(actor(), options()) :: boolean() ``` Whether or not your check requires the original data of a changeset (if applicable) [](Ash.Policy.Check.html#c:strict_check/3) # strict\_check(actor, authorizer, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L33) ``` @callback strict_check(actor(), authorizer(), options()) :: {:ok, boolean() | :unknown} | {:error, term()} ``` Strict checks should be cheap, and should never result in external calls (like database or domain) It should return `{:ok, true}` if it can tell that the request is authorized, and `{:ok, false}` if it can tell that it is not. If unsure, it should return `{:ok, :unknown}` [](Ash.Policy.Check.html#c:type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L71) ``` @callback type() :: check_type() ``` The type of the check `:manual` checks must be written by hand as standard check modules `:filter` checks can use [`Ash.Policy.FilterCheck`](Ash.Policy.FilterCheck.html) for simplicity `:simple` checks can use [`Ash.Policy.SimpleCheck`](Ash.Policy.SimpleCheck.html) for simplicity # [](Ash.Policy.Check.html#functions)Functions [](Ash.Policy.Check.html#defines_auto_filter?/1) # defines\_auto\_filter?(module) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L79) [](Ash.Policy.Check.html#defines_check?/1) # defines\_check?(module) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check.ex#L75) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Loading (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/loading.ex#L1 "View Source") This check is true when the field or relationship, or path to field, is being loaded and false when it is not. # [](Ash.Policy.Check.Loading.html#summary)Summary ## [Functions](Ash.Policy.Check.Loading.html#functions) [eager\_evaluate?()](Ash.Policy.Check.Loading.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.Loading.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.Loading.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.Loading.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.Loading.html#functions)Functions [](Ash.Policy.Check.Loading.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/loading.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.Loading.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/loading.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.Loading.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/loading.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.Loading.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/loading.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Matches (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/matches.ex#L1 "View Source") This check is true when the specified function returns true # [](Ash.Policy.Check.Matches.html#summary)Summary ## [Functions](Ash.Policy.Check.Matches.html#functions) [eager\_evaluate?()](Ash.Policy.Check.Matches.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.Matches.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [requires\_original\_data?(\_, \_)](Ash.Policy.Check.Matches.html#requires_original_data?/2) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [strict\_check(actor, context, opts)](Ash.Policy.Check.Matches.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.Matches.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.Matches.html#functions)Functions [](Ash.Policy.Check.Matches.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/matches.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.Matches.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/matches.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.Matches.html#requires_original_data?/2) # requires\_original\_data?(\_, \_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/matches.ex#L3) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [](Ash.Policy.Check.Matches.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/matches.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.Matches.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/matches.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.RelatesToActorVia (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L1 "View Source") This check passes if the data relates to the actor via the specified relationship or path of relationships. # [](Ash.Policy.Check.RelatesToActorVia.html#summary)Summary ## [Functions](Ash.Policy.Check.RelatesToActorVia.html#functions) [auto\_filter(actor, authorizer, opts)](Ash.Policy.Check.RelatesToActorVia.html#auto_filter/3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [auto\_filter\_not(actor, authorizer, opts)](Ash.Policy.Check.RelatesToActorVia.html#auto_filter_not/3) [check(actor, data, authorizer, opts)](Ash.Policy.Check.RelatesToActorVia.html#check/4) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [eager\_evaluate?()](Ash.Policy.Check.RelatesToActorVia.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [expand\_description(actor, authorizer, opts)](Ash.Policy.Check.RelatesToActorVia.html#expand_description/3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [prefer\_expanded\_description?()](Ash.Policy.Check.RelatesToActorVia.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [requires\_original\_data?(\_, \_)](Ash.Policy.Check.RelatesToActorVia.html#requires_original_data?/2) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [strict\_check(actor, authorizer, opts)](Ash.Policy.Check.RelatesToActorVia.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [strict\_check\_context(opts)](Ash.Policy.Check.RelatesToActorVia.html#strict_check_context/1) [type()](Ash.Policy.Check.RelatesToActorVia.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.RelatesToActorVia.html#functions)Functions [](Ash.Policy.Check.RelatesToActorVia.html#auto_filter/3) # auto\_filter(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [](Ash.Policy.Check.RelatesToActorVia.html#auto_filter_not/3) # auto\_filter\_not(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) [](Ash.Policy.Check.RelatesToActorVia.html#check/4) # check(actor, data, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [](Ash.Policy.Check.RelatesToActorVia.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.RelatesToActorVia.html#expand_description/3) # expand\_description(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [](Ash.Policy.Check.RelatesToActorVia.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.RelatesToActorVia.html#requires_original_data?/2) # requires\_original\_data?(\_, \_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [](Ash.Policy.Check.RelatesToActorVia.html#strict_check/3) # strict\_check(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.RelatesToActorVia.html#strict_check_context/1) # strict\_check\_context(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) [](Ash.Policy.Check.RelatesToActorVia.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relates_to_actor_via.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.RelatingToActor (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L1 "View Source") This check is true when the specified relationship is being changed to the current actor. # [](Ash.Policy.Check.RelatingToActor.html#summary)Summary ## [Functions](Ash.Policy.Check.RelatingToActor.html#functions) [auto\_filter(actor, authorizer, opts)](Ash.Policy.Check.RelatingToActor.html#auto_filter/3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [auto\_filter\_not(actor, authorizer, opts)](Ash.Policy.Check.RelatingToActor.html#auto_filter_not/3) [check(actor, data, authorizer, opts)](Ash.Policy.Check.RelatingToActor.html#check/4) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [eager\_evaluate?()](Ash.Policy.Check.RelatingToActor.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [expand\_description(actor, authorizer, opts)](Ash.Policy.Check.RelatingToActor.html#expand_description/3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [prefer\_expanded\_description?()](Ash.Policy.Check.RelatingToActor.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [reject(actor, authorizer, opts)](Ash.Policy.Check.RelatingToActor.html#reject/3) Callback implementation for [`Ash.Policy.FilterCheck.reject/3`](Ash.Policy.FilterCheck.html#c:reject/3). [requires\_original\_data?(\_, \_)](Ash.Policy.Check.RelatingToActor.html#requires_original_data?/2) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [strict\_check(actor, authorizer, opts)](Ash.Policy.Check.RelatingToActor.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [strict\_check\_context(opts)](Ash.Policy.Check.RelatingToActor.html#strict_check_context/1) [type()](Ash.Policy.Check.RelatingToActor.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.RelatingToActor.html#functions)Functions [](Ash.Policy.Check.RelatingToActor.html#auto_filter/3) # auto\_filter(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.auto_filter/3`](Ash.Policy.Check.html#c:auto_filter/3). [](Ash.Policy.Check.RelatingToActor.html#auto_filter_not/3) # auto\_filter\_not(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) [](Ash.Policy.Check.RelatingToActor.html#check/4) # check(actor, data, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.check/4`](Ash.Policy.Check.html#c:check/4). [](Ash.Policy.Check.RelatingToActor.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.RelatingToActor.html#expand_description/3) # expand\_description(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.expand_description/3`](Ash.Policy.Check.html#c:expand_description/3). [](Ash.Policy.Check.RelatingToActor.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.RelatingToActor.html#reject/3) # reject(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.FilterCheck.reject/3`](Ash.Policy.FilterCheck.html#c:reject/3). [](Ash.Policy.Check.RelatingToActor.html#requires_original_data?/2) # requires\_original\_data?(\_, \_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.requires_original_data?/2`](Ash.Policy.Check.html#c:requires_original_data?/2). [](Ash.Policy.Check.RelatingToActor.html#strict_check/3) # strict\_check(actor, authorizer, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.RelatingToActor.html#strict_check_context/1) # strict\_check\_context(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) [](Ash.Policy.Check.RelatingToActor.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/relating_to_actor.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Resource (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/resource.ex#L1 "View Source") This check is true when the resource matches the provided resource name or names. # [](Ash.Policy.Check.Resource.html#summary)Summary ## [Functions](Ash.Policy.Check.Resource.html#functions) [eager\_evaluate?()](Ash.Policy.Check.Resource.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.Resource.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.Resource.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.Resource.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.Resource.html#functions)Functions [](Ash.Policy.Check.Resource.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/resource.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.Resource.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/resource.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.Resource.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/resource.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.Resource.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/resource.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Selecting (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/selecting.ex#L1 "View Source") This check is true when the field is being selected and false when it is not. # [](Ash.Policy.Check.Selecting.html#summary)Summary ## [Functions](Ash.Policy.Check.Selecting.html#functions) [eager\_evaluate?()](Ash.Policy.Check.Selecting.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.Selecting.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.Selecting.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.Selecting.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.Selecting.html#functions)Functions [](Ash.Policy.Check.Selecting.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/selecting.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.Selecting.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/selecting.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.Selecting.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/selecting.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.Selecting.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/selecting.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Check.Static (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/static.ex#L1 "View Source") This check is always the result provided # [](Ash.Policy.Check.Static.html#summary)Summary ## [Functions](Ash.Policy.Check.Static.html#functions) [eager\_evaluate?()](Ash.Policy.Check.Static.html#eager_evaluate?/0) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [prefer\_expanded\_description?()](Ash.Policy.Check.Static.html#prefer_expanded_description?/0) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [strict\_check(actor, context, opts)](Ash.Policy.Check.Static.html#strict_check/3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [type()](Ash.Policy.Check.Static.html#type/0) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). # [](Ash.Policy.Check.Static.html#functions)Functions [](Ash.Policy.Check.Static.html#eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/static.ex#L3) Callback implementation for [`Ash.Policy.Check.eager_evaluate?/0`](Ash.Policy.Check.html#c:eager_evaluate?/0). [](Ash.Policy.Check.Static.html#prefer_expanded_description?/0) # prefer\_expanded\_description?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/static.ex#L3) Callback implementation for [`Ash.Policy.Check.prefer_expanded_description?/0`](Ash.Policy.Check.html#c:prefer_expanded_description?/0). [](Ash.Policy.Check.Static.html#strict_check/3) # strict\_check(actor, context, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/static.ex#L3) Callback implementation for [`Ash.Policy.Check.strict_check/3`](Ash.Policy.Check.html#c:strict_check/3). [](Ash.Policy.Check.Static.html#type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/check/static.ex#L3) Callback implementation for [`Ash.Policy.Check.type/0`](Ash.Policy.Check.html#c:type/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.FieldPolicy (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/field_policy.ex#L1 "View Source") Represents a field policy in an Ash.Resource # [](Ash.Policy.FieldPolicy.html#summary)Summary ## [Types](Ash.Policy.FieldPolicy.html#types) [t()](Ash.Policy.FieldPolicy.html#t:t/0) # [](Ash.Policy.FieldPolicy.html#types)Types [](Ash.Policy.FieldPolicy.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/field_policy.ex#L13) ``` @type t() :: %Ash.Policy.FieldPolicy{ __identifier__: term(), access_type: term(), bypass?: term(), condition: term(), description: term(), fields: term(), policies: term() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.FilterCheck behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/filter_check.ex#L1 "View Source") A type of check that is represented by a filter statement That filter statement can be templated, currently only supporting `{:_actor, field}` which will replace that portion of the filter with the appropriate field value from the actor and `{:_actor, :_primary_key}` which will replace the value with a keyword list of the primary key fields of an actor to their values, like `[id: 1]`. If the actor is not present `{:_actor, field}` becomes `nil`, and `{:_actor, :_primary_key}` becomes `false`. You can customize what the "negative" filter looks like by defining [`reject/3`](Ash.Policy.FilterCheck.html#c:reject/3). This is important for filters over related data. For example, given an `owner` relationship and a data layer like `ash_postgres` where `column != NULL` does *not* evaluate to true (see postgres docs on NULL for more): ``` # The opposite of `owner.id == 1` # in most cases is not `not(owner.id == 1)` # because in postgres that would be `NOT (owner.id = NULL)` in cases where there was no owner # A better opposite would be `owner.id != 1 or is_nil(owner.id)` # alternatively `not(owner.id == 1) or is_nil(owner.id)` ``` By being able to customize the `reject` filter, you can use related filters in your policies. Without it, they will likely have undesired effects. # [](Ash.Policy.FilterCheck.html#summary)Summary ## [Types](Ash.Policy.FilterCheck.html#types) [context()](Ash.Policy.FilterCheck.html#t:context/0) [options()](Ash.Policy.FilterCheck.html#t:options/0) ## [Callbacks](Ash.Policy.FilterCheck.html#callbacks) [filter(actor, context, options)](Ash.Policy.FilterCheck.html#c:filter/3) [reject(actor, context, options)](Ash.Policy.FilterCheck.html#c:reject/3) ## [Functions](Ash.Policy.FilterCheck.html#functions) [is\_filter\_check?(module)](Ash.Policy.FilterCheck.html#is_filter_check?/1) # [](Ash.Policy.FilterCheck.html#types)Types [](Ash.Policy.FilterCheck.html#t:context/0) # context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/filter_check.ex#L29) ``` @type context() :: %{ :action => Ash.Resource.Actions.action(), :resource => Ash.Resource.t(), :domain => Ash.Domain.t(), optional(:query) => Ash.Query.t(), optional(:changeset) => Ash.Changeset.t(), optional(:action_input) => Ash.ActionInput.t(), optional(any()) => any() } ``` [](Ash.Policy.FilterCheck.html#t:options/0) # options() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/filter_check.ex#L28) ``` @type options() :: Keyword.t() ``` # [](Ash.Policy.FilterCheck.html#callbacks)Callbacks [](Ash.Policy.FilterCheck.html#c:filter/3) # filter(actor, context, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/filter_check.ex#L39) ``` @callback filter(actor :: term(), context(), options()) :: Keyword.t() | Ash.Expr.t() ``` [](Ash.Policy.FilterCheck.html#c:reject/3) # reject(actor, context, options) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/filter_check.ex#L40) ``` @callback reject(actor :: term(), context(), options()) :: Keyword.t() | Ash.Expr.t() ``` # [](Ash.Policy.FilterCheck.html#functions)Functions [](Ash.Policy.FilterCheck.html#is_filter_check?/1) # is\_filter\_check?(module) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/filter_check.ex#L382) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Info (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L1 "View Source") An authorization extension for ash resources. For more information, see [`Ash.Policy.Authorizer`](Ash.Policy.Authorizer.html) # [](Ash.Policy.Info.html#summary)Summary ## [Functions](Ash.Policy.Info.html#functions) [default\_access\_type(resource)](Ash.Policy.Info.html#default_access_type/1) [describe\_resource(domain, resource)](Ash.Policy.Info.html#describe_resource/2) [field\_policies(resource)](Ash.Policy.Info.html#field_policies/1) [field\_policies\_for\_field(resource, field)](Ash.Policy.Info.html#field_policies_for_field/2) Gets the field policies relevant to a given field [log\_policy\_breakdowns()](Ash.Policy.Info.html#log_policy_breakdowns/0) Whether or not Ash policy authorizer is configured to log policy breakdowns [log\_successful\_policy\_breakdowns()](Ash.Policy.Info.html#log_successful_policy_breakdowns/0) Whether or not Ash policy authorizer is configured to log successful policy breakdowns [policies(domain \\\\ nil, resource)](Ash.Policy.Info.html#policies/2) [private\_fields\_policy(resource)](Ash.Policy.Info.html#private_fields_policy/1) [show\_policy\_breakdowns?()](Ash.Policy.Info.html#show_policy_breakdowns?/0) Whether or not Ash policy authorizer is configured to show policy breakdowns in error messages [strict\_check(actor, query, domain)](Ash.Policy.Info.html#strict_check/3) A utility to determine if a given query/changeset would pass authorization. # [](Ash.Policy.Info.html#functions)Functions [](Ash.Policy.Info.html#default_access_type/1) # default\_access\_type(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L187) [](Ash.Policy.Info.html#describe_resource/2) # describe\_resource(domain, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L96) [](Ash.Policy.Info.html#field_policies/1) # field\_policies(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L140) [](Ash.Policy.Info.html#field_policies_for_field/2) # field\_policies\_for\_field(resource, field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L26) Gets the field policies relevant to a given field [](Ash.Policy.Info.html#log_policy_breakdowns/0) # log\_policy\_breakdowns() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L16) Whether or not Ash policy authorizer is configured to log policy breakdowns [](Ash.Policy.Info.html#log_successful_policy_breakdowns/0) # log\_successful\_policy\_breakdowns() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L21) Whether or not Ash policy authorizer is configured to log successful policy breakdowns [](Ash.Policy.Info.html#policies/2) # policies(domain \\\\ nil, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L158) [](Ash.Policy.Info.html#private_fields_policy/1) # private\_fields\_policy(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L149) [](Ash.Policy.Info.html#show_policy_breakdowns?/0) # show\_policy\_breakdowns?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L11) Whether or not Ash policy authorizer is configured to show policy breakdowns in error messages [](Ash.Policy.Info.html#strict_check/3) # strict\_check(actor, query, domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/info.ex#L35) A utility to determine if a given query/changeset would pass authorization. *This is still experimental.* [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.PolicyGroup (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/policy_group.ex#L1 "View Source") Represents a policy group on an Ash.Resource [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Policy (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/policy.ex#L1 "View Source") Represents a policy on an Ash.Resource # [](Ash.Policy.Policy.html#summary)Summary ## [Types](Ash.Policy.Policy.html#types) [t()](Ash.Policy.Policy.html#t:t/0) ## [Functions](Ash.Policy.Policy.html#functions) [at\_least\_one\_policy\_expression(policies)](Ash.Policy.Policy.html#at_least_one_policy_expression/1) [fetch\_fact(facts, arg2)](Ash.Policy.Policy.html#fetch_fact/2) [fetch\_or\_strict\_check\_fact(authorizer, arg2)](Ash.Policy.Policy.html#fetch_or_strict_check_fact/2) [solve(authorizer)](Ash.Policy.Policy.html#solve/1) # [](Ash.Policy.Policy.html#types)Types [](Ash.Policy.Policy.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/policy.ex#L14) ``` @type t() :: %Ash.Policy.Policy{ access_type: term(), bypass?: term(), condition: term(), description: term(), policies: term() } ``` # [](Ash.Policy.Policy.html#functions)Functions [](Ash.Policy.Policy.html#at_least_one_policy_expression/1) # at\_least\_one\_policy\_expression(policies) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/policy.ex#L132) [](Ash.Policy.Policy.html#fetch_fact/2) # fetch\_fact(facts, arg2) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/policy.ex#L217) [](Ash.Policy.Policy.html#fetch_or_strict_check_fact/2) # fetch\_or\_strict\_check\_fact(authorizer, arg2) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/policy.ex#L152) [](Ash.Policy.Policy.html#solve/1) # solve(authorizer) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/policy.ex#L23) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.SimpleCheck behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/simple_check.ex#L1 "View Source") A type of check that operates only on request context, never on the data Define [`match?/3`](Ash.Policy.SimpleCheck.html#c:match?/3), which gets the actor, request context, and opts, and returns true or false # [](Ash.Policy.SimpleCheck.html#summary)Summary ## [Types](Ash.Policy.SimpleCheck.html#types) [actor()](Ash.Policy.SimpleCheck.html#t:actor/0) [context()](Ash.Policy.SimpleCheck.html#t:context/0) [options()](Ash.Policy.SimpleCheck.html#t:options/0) ## [Callbacks](Ash.Policy.SimpleCheck.html#callbacks) [match?(actor, context, options)](Ash.Policy.SimpleCheck.html#c:match?/3) Whether or not the request matches the check # [](Ash.Policy.SimpleCheck.html#types)Types [](Ash.Policy.SimpleCheck.html#t:actor/0) # actor() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/simple_check.ex#L7) ``` @type actor() :: Ash.Policy.Check.actor() ``` [](Ash.Policy.SimpleCheck.html#t:context/0) # context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/simple_check.ex#L8) ``` @type context() :: Ash.Policy.Authorizer.t() ``` [](Ash.Policy.SimpleCheck.html#t:options/0) # options() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/simple_check.ex#L9) ``` @type options() :: Keyword.t() ``` # [](Ash.Policy.SimpleCheck.html#callbacks)Callbacks [](Ash.Policy.SimpleCheck.html#c:match?/3) # match?(actor, context, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/policy/simple_check.ex#L12) ``` @callback match?(actor(), context(), options()) :: boolean() | {:ok, boolean()} | {:error, term()} ``` Whether or not the request matches the check [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.ProcessHelpers (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/process_helpers.ex#L1 "View Source") Helpers for working with processes and Ash actions. # [](Ash.ProcessHelpers.html#summary)Summary ## [Functions](Ash.ProcessHelpers.html#functions) [async(func, opts)](Ash.ProcessHelpers.html#async/2) Creates a task that will properly transfer the ash context to the new process [get\_context\_for\_transfer(opts \\\\ \[\])](Ash.ProcessHelpers.html#get_context_for_transfer/1) Gets all of the ash context so it can be set into a new process. [task\_with\_timeout(fun, resource, timeout, name, tracer)](Ash.ProcessHelpers.html#task_with_timeout/5) Creates a task that will properly transfer the ash context to the new process, and timeout if it takes longer than the given timeout [transfer\_context(tracer\_context, opts \\\\ \[\])](Ash.ProcessHelpers.html#transfer_context/2) # [](Ash.ProcessHelpers.html#functions)Functions [](Ash.ProcessHelpers.html#async/2) # async(func, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/process_helpers.ex#L30) Creates a task that will properly transfer the ash context to the new process [](Ash.ProcessHelpers.html#get_context_for_transfer/1) # get\_context\_for\_transfer(opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/process_helpers.ex#L12) ``` @spec get_context_for_transfer(opts :: Keyword.t()) :: term() ``` Gets all of the ash context so it can be set into a new process. Use [`transfer_context/1`](Ash.ProcessHelpers.html#transfer_context/1) in the new process to set the context. [](Ash.ProcessHelpers.html#task_with_timeout/5) # task\_with\_timeout(fun, resource, timeout, name, tracer) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/process_helpers.ex#L62) Creates a task that will properly transfer the ash context to the new process, and timeout if it takes longer than the given timeout [](Ash.ProcessHelpers.html#transfer_context/2) # transfer\_context(tracer\_context, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/process_helpers.ex#L21) ``` @spec transfer_context(term(), opts :: Keyword.t()) :: :ok ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Aggregate (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/aggregate.ex#L1 "View Source") Represents an aggregated association value # [](Ash.Query.Aggregate.html#summary)Summary ## [Types](Ash.Query.Aggregate.html#types) [kind()](Ash.Query.Aggregate.html#t:kind/0) [t()](Ash.Query.Aggregate.html#t:t/0) ## [Functions](Ash.Query.Aggregate.html#functions) [default\_value(atom)](Ash.Query.Aggregate.html#default_value/1) [new(resource, name, kind, opts \\\\ \[\])](Ash.Query.Aggregate.html#new/4) Create a new aggregate, used with `Query.aggregate` or `Ash.aggregate` [new!(resource, name, kind, opts \\\\ \[\])](Ash.Query.Aggregate.html#new!/4) # [](Ash.Query.Aggregate.html#types)Types [](Ash.Query.Aggregate.html#t:kind/0) # kind() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/aggregate.ex#L30) ``` @type kind() :: :custom | :exists | :avg | :min | :max | :list | :sum | :first | :count ``` [](Ash.Query.Aggregate.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/aggregate.ex#L27) ``` @type t() :: %Ash.Query.Aggregate{ agg_name: term(), authorize?: term(), constraints: term(), context: term(), default_value: term(), field: term(), filterable?: term(), implementation: term(), include_nil?: term(), join_filters: term(), kind: term(), load: term(), name: term(), query: term(), read_action: term(), relationship_path: term(), resource: term(), sensitive?: term(), sortable?: term(), type: term(), uniq?: term() } ``` # [](Ash.Query.Aggregate.html#functions)Functions [](Ash.Query.Aggregate.html#default_value/1) # default\_value(atom) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/aggregate.ex#L507) [](Ash.Query.Aggregate.html#new/4) # new(resource, name, kind, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/aggregate.ex#L183) Create a new aggregate, used with `Query.aggregate` or `Ash.aggregate` Options: - `:path` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - The relationship path to aggregate over. Only used when adding aggregates to a query. The default value is `[]`. - `:query` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A base query to use for the aggregate, or a keyword list to be passed to [`Ash.Query.build/2`](Ash.Query.html#build/2) - `:field` - The field to use for the aggregate. Not necessary for all aggregate types. - `:expr` ([`term/0`](../elixir/typespecs.html#built-in-types)) - An expression to aggregate, cannot be used with `field`. - `:expr_type` - The type of the expression, required if `expr` is used. - `:arguments` ([`map/0`](../elixir/typespecs.html#basic-types)) - Arguments to pass to the field, if field is a calculation. - `:default` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A default value to use for the aggregate if it returns `nil`. - `:filterable?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not this aggregate may be used in filters. The default value is `true`. - `:sortable?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not this aggregate may be used in sorts. The default value is `true`. - `:type` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A type to use for the aggregate. - `:constraints` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Type constraints to use for the aggregate. The default value is `[]`. - `:implementation` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The implementation for any custom aggregates. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The read action to use for the aggregate, defaults to the primary read action. - `:uniq?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to only consider unique values. Only relevant for `count` and `list` aggregates. The default value is `false`. - `:include_nil?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to include `nil` values in the aggregate. Only relevant for `list` and `first` aggregates. The default value is `false`. - `:join_filters` (map of one or a list of [`atom/0`](../elixir/typespecs.html#basic-types) keys and [`term/0`](../elixir/typespecs.html#built-in-types) values) - A map of relationship paths (an atom or list of atoms), to an expression to apply when fetching the aggregate data. See the aggregates guide for more. The default value is `%{}`. - `:sensitive?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not references to this aggregate will be considered sensitive The default value is `false`. - `:tenant` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The tenant to use for the aggregate, if applicable. The default value is `nil`. - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not the aggregate query should authorize based on the target action. See `Ash.Resource.Dsl.aggregates.count` for more information. The default value is `true`. [](Ash.Query.Aggregate.html#new!/4) # new!(resource, name, kind, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/aggregate.ex#L39) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.BooleanExpression (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/boolean_expression.ex#L1 "View Source") Represents a boolean expression # [](Ash.Query.BooleanExpression.html#summary)Summary ## [Functions](Ash.Query.BooleanExpression.html#functions) [new(op, left, right)](Ash.Query.BooleanExpression.html#new/3) [optimized\_new(op, left, right)](Ash.Query.BooleanExpression.html#optimized_new/3) # [](Ash.Query.BooleanExpression.html#functions)Functions [](Ash.Query.BooleanExpression.html#new/3) # new(op, left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/boolean_expression.ex#L10) [](Ash.Query.BooleanExpression.html#optimized_new/3) # optimized\_new(op, left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/boolean_expression.ex#L27) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Calculation (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/calculation.ex#L1 "View Source") Represents a calculated attribute requested on a query # [](Ash.Query.Calculation.html#summary)Summary ## [Types](Ash.Query.Calculation.html#types) [t()](Ash.Query.Calculation.html#t:t/0) ## [Functions](Ash.Query.Calculation.html#functions) [from\_resource\_calculation(resource, name, opts \\\\ \[\])](Ash.Query.Calculation.html#from_resource_calculation/3) Creates a new query calculation from a resource calculation. [from\_resource\_calculation!(resource, name, opts \\\\ \[\])](Ash.Query.Calculation.html#from_resource_calculation!/3) Creates a new query calculation from a resource calculation, raising any errors. [new(name, module, calc\_opts, type, constraints, opts \\\\ \[\])](Ash.Query.Calculation.html#new/6) Creates a new query calculation. # [](Ash.Query.Calculation.html#types)Types [](Ash.Query.Calculation.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/calculation.ex#L21) ``` @type t() :: %Ash.Query.Calculation{ async?: term(), calc_name: term(), constraints: term(), context: term(), filterable?: term(), load: term(), module: term(), name: term(), opts: term(), required_loads: term(), select: term(), sensitive?: term(), sortable?: term(), type: term() } ``` # [](Ash.Query.Calculation.html#functions)Functions [](Ash.Query.Calculation.html#from_resource_calculation/3) # from\_resource\_calculation(resource, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/calculation.ex#L192) Creates a new query calculation from a resource calculation. ## [](Ash.Query.Calculation.html#from_resource_calculation/3-options)Options - `:args` ([`map/0`](../elixir/typespecs.html#basic-types)) - Arguments to pass to the calculation The default value is `%{}`. - `:source_context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context from the source query or changeset. The default value is `%{}`. [](Ash.Query.Calculation.html#from_resource_calculation!/3) # from\_resource\_calculation!(resource, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/calculation.ex#L171) Creates a new query calculation from a resource calculation, raising any errors. See [`from_resource_calculation/3`](Ash.Query.Calculation.html#from_resource_calculation/3) for more. [](Ash.Query.Calculation.html#new/6) # new(name, module, calc\_opts, type, constraints, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/calculation.ex#L95) Creates a new query calculation. ## [](Ash.Query.Calculation.html#new/6-options)Options - `:arguments` ([`map/0`](../elixir/typespecs.html#basic-types)) - Arguments to pass to the calculation The default value is `%{}`. - `:async?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not this calculation should be run asynchronously The default value is `false`. - `:filterable?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not this calculation can be filtered on The default value is `true`. - `:sortable?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not this calculation can be sorted on The default value is `true`. - `:sensitive?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not references to this calculation will be considered sensitive The default value is `false`. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Loads that are required for the calculation. - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The actor performing the calculation. - `:tenant` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The tenant performing the calculation. - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not authorization is being performed - `:tracer` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The tracer or tracers used in the calculation. - `:source_context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context from the source query or changeset. The default value is `%{}`. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Call (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/call.ex#L1 "View Source") Represents a function call/AST node in an Ash query expression [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Exists (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/exists.ex#L1 "View Source") Determines if a given related entity exists. # [](Ash.Query.Exists.html#summary)Summary ## [Functions](Ash.Query.Exists.html#functions) [can\_return\_nil?(\_)](Ash.Query.Exists.html#can_return_nil?/1) [new(path, expr, at\_path \\\\ \[\])](Ash.Query.Exists.html#new/3) # [](Ash.Query.Exists.html#functions)Functions [](Ash.Query.Exists.html#can_return_nil?/1) # can\_return\_nil?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/exists.ex#L22) [](Ash.Query.Exists.html#new/3) # new(path, expr, at\_path \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/exists.ex#L8) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Ago (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/ago.ex#L1 "View Source") Subtracts the given interval from the current time in UTC. For example: deleted\_at &gt; ago(7, :day) Documentation + available intervals inspired by the corresponding ecto interval implementation # [](Ash.Query.Function.Ago.html#summary)Summary ## [Functions](Ash.Query.Function.Ago.html#functions) [args()](Ash.Query.Function.Ago.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Ago.html#functions)Functions [](Ash.Query.Function.Ago.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/ago.ex#L13) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.At (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/at.ex#L1 "View Source") Gets an element in the list by index # [](Ash.Query.Function.At.html#summary)Summary ## [Functions](Ash.Query.Function.At.html#functions) [args()](Ash.Query.Function.At.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.At.html#functions)Functions [](Ash.Query.Function.At.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/at.ex#L8) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.CompositeType (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/composite_type.ex#L1 "View Source") Constructs a composite type in a way that is natively understood by the data layer To do this, provide a tuple matching the format expected by the type in question. Check that type's documentation for this information. # [](Ash.Query.Function.CompositeType.html#summary)Summary ## [Functions](Ash.Query.Function.CompositeType.html#functions) [args()](Ash.Query.Function.CompositeType.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.CompositeType.html#functions)Functions [](Ash.Query.Function.CompositeType.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/composite_type.ex#L11) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Contains (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/contains.ex#L1 "View Source") Returns true if the first string contains the second. Case insensitive strings are accounted for on either side. contains("foo", "fo") true contains(%Ash.CiString{:string "foo"}, "FoO") true contains("foo", %Ash.CiString{:string "FOO"}) true # [](Ash.Query.Function.Contains.html#summary)Summary ## [Functions](Ash.Query.Function.Contains.html#functions) [args()](Ash.Query.Function.Contains.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Contains.html#functions)Functions [](Ash.Query.Function.Contains.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/contains.ex#L20) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.CountNils (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/count_nils.ex#L1 "View Source") Returns the count of nil. ``` count_nil([nil, 1, nil]) # 2 ``` # [](Ash.Query.Function.CountNils.html#summary)Summary ## [Functions](Ash.Query.Function.CountNils.html#functions) [args()](Ash.Query.Function.CountNils.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.CountNils.html#functions)Functions [](Ash.Query.Function.CountNils.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/count_nils.ex#L9) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.DateAdd (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/date_add.ex#L1 "View Source") Adds the given interval to the current time in UTC For example: activates\_at &lt; date\_add(today(), 7, :day) Documentation + available intervals inspired by the corresponding ecto interval implementation # [](Ash.Query.Function.DateAdd.html#summary)Summary ## [Functions](Ash.Query.Function.DateAdd.html#functions) [args()](Ash.Query.Function.DateAdd.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.DateAdd.html#functions)Functions [](Ash.Query.Function.DateAdd.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/date_add.ex#L15) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.DateTimeAdd (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/datetime_add.ex#L1 "View Source") Adds the given interval to the current time in UTC For example: activates\_at &lt; datetime\_add(now(), 7, :day) Documentation + available intervals inspired by the corresponding ecto interval implementation # [](Ash.Query.Function.DateTimeAdd.html#summary)Summary ## [Functions](Ash.Query.Function.DateTimeAdd.html#functions) [args()](Ash.Query.Function.DateTimeAdd.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.DateTimeAdd.html#functions)Functions [](Ash.Query.Function.DateTimeAdd.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/datetime_add.ex#L13) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Error (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/error.ex#L1 "View Source") If the predicate is truthy, the provided exception is raised with the provided values. This exception is not "raised" in the Elixir sense, but the entire expression fails to evaluate with the given error. Various data layers will handle this differently. # [](Ash.Query.Function.Error.html#summary)Summary ## [Functions](Ash.Query.Function.Error.html#functions) [args()](Ash.Query.Function.Error.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Error.html#functions)Functions [](Ash.Query.Function.Error.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/error.ex#L10) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Fragment (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/fragment.ex#L1 "View Source") Adds the given interval from the current time in UTC. For example: expires\_at &lt; from\_now(7, :day) Documentation + available intervals inspired by the corresponding ecto interval implementation # [](Ash.Query.Function.Fragment.html#summary)Summary ## [Functions](Ash.Query.Function.Fragment.html#functions) [args()](Ash.Query.Function.Fragment.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [casted\_new(list)](Ash.Query.Function.Fragment.html#casted_new/1) # [](Ash.Query.Function.Fragment.html#functions)Functions [](Ash.Query.Function.Fragment.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/fragment.ex#L15) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [](Ash.Query.Function.Fragment.html#casted_new/1) # casted\_new(list) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/fragment.ex#L56) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.FromNow (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/from_now.ex#L1 "View Source") Adds the given interval from the current time in UTC. For example: expires\_at &lt; from\_now(7, :day) Documentation + available intervals inspired by the corresponding ecto interval implementation # [](Ash.Query.Function.FromNow.html#summary)Summary ## [Functions](Ash.Query.Function.FromNow.html#functions) [args()](Ash.Query.Function.FromNow.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.FromNow.html#functions)Functions [](Ash.Query.Function.FromNow.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/from_now.ex#L13) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.GetPath (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/get_path.ex#L1 "View Source") Gets the value at the provided path in the value, which must be a map or embed. If you are using a datalayer that provides a `type` function (like AshPostgres), it is a good idea to wrap your call in that function, e.g `type(author[:bio][:title], :string)`, since data layers that depend on knowing types may not be able to infer the type from the path. Ash may eventually be able to figure out the type, in the case that the path consists of only embedded attributes. If an atom key is provided, access is *indiscriminate* of atoms vs strings. The atom key is checked first. If a string key is provided, that is the only thing that is checked. If the value will or may be a struct, be sure to use atoms. The data layer may handle this differently, for example, AshPostgres only checks strings at the data layer (because thats all it can be in the database anyway). Available in query expressions using bracket syntax, e.g `foo[:bar][:baz]`. # [](Ash.Query.Function.GetPath.html#summary)Summary ## [Functions](Ash.Query.Function.GetPath.html#functions) [args()](Ash.Query.Function.GetPath.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.GetPath.html#functions)Functions [](Ash.Query.Function.GetPath.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/get_path.ex#L20) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L1 "View Source") A function is a predicate with an arguments list. For more information on being a predicate, see [`Ash.Filter.Predicate`](Ash.Filter.Predicate.html). Most of the complexities are there. A function must meet both behaviours. # [](Ash.Query.Function.html#summary)Summary ## [Types](Ash.Query.Function.html#types) [arg()](Ash.Query.Function.html#t:arg/0) ## [Callbacks](Ash.Query.Function.html#callbacks) [args()](Ash.Query.Function.html#c:args/0) The number and types of arguments supported. [can\_return\_nil?(func)](Ash.Query.Function.html#c:can_return_nil?/1) Whether or not the function return nil. [eager\_evaluate?()](Ash.Query.Function.html#c:eager_evaluate?/0) Whether or not the function can be evaluated eagerly. For example, `now()` cannot be. [evaluate(func)](Ash.Query.Function.html#c:evaluate/1) Evaluate a function when all arguments are known valid values [evaluate\_nil\_inputs?()](Ash.Query.Function.html#c:evaluate_nil_inputs?/0) If `true`, will be allowed to evaluate `nil` inputs. [name()](Ash.Query.Function.html#c:name/0) The name of the function [new(list)](Ash.Query.Function.html#c:new/1) Instantiate a new function with the provided arguments [partial\_evaluate(func)](Ash.Query.Function.html#c:partial_evaluate/1) Evaluate a function when some or no arguments are known valid values [predicate?()](Ash.Query.Function.html#c:predicate?/0) Whether or not the function is a predicate (takes a reference as the first argument, a value as the second, and returns a boolean) [private?()](Ash.Query.Function.html#c:private?/0) Whether or not the function should be usable when parsing input. [returns()](Ash.Query.Function.html#c:returns/0) The return type for each corresponding set of args. ## [Functions](Ash.Query.Function.html#functions) [evaluate(func)](Ash.Query.Function.html#evaluate/1) Evaluate the operator with provided inputs [new(mod, args)](Ash.Query.Function.html#new/2) [ordinal(num)](Ash.Query.Function.html#ordinal/1) Attaches the appropriate suffix to refer to an ordinal number, e.g 1 -&gt; "1st" [try\_cast\_arguments(configured\_args, args)](Ash.Query.Function.html#try_cast_arguments/2) # [](Ash.Query.Function.html#types)Types [](Ash.Query.Function.html#t:arg/0) # arg() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L11) ``` @type arg() :: any() ``` # [](Ash.Query.Function.html#callbacks)Callbacks [](Ash.Query.Function.html#c:args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L15) ``` @callback args() :: [arg()] | :var_args ``` The number and types of arguments supported. [](Ash.Query.Function.html#c:can_return_nil?/1) # can\_return\_nil?(func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L41) ``` @callback can_return_nil?(func :: map()) :: boolean() ``` Whether or not the function return nil. [](Ash.Query.Function.html#c:eager_evaluate?/0) # eager\_evaluate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L35) ``` @callback eager_evaluate?() :: boolean() ``` Whether or not the function can be evaluated eagerly. For example, `now()` cannot be. [](Ash.Query.Function.html#c:evaluate/1) # evaluate(func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L31) ``` @callback evaluate(func :: map()) :: :unknown | {:known, term()} | {:error, term()} ``` Evaluate a function when all arguments are known valid values [](Ash.Query.Function.html#c:evaluate_nil_inputs?/0) # evaluate\_nil\_inputs?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L48) ``` @callback evaluate_nil_inputs?() :: boolean() ``` If `true`, will be allowed to evaluate `nil` inputs. If `false` (the default), any `nil` inputs will cause a `nil` return. [](Ash.Query.Function.html#c:name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L27) ``` @callback name() :: atom() ``` The name of the function [](Ash.Query.Function.html#c:new/1) # new(list) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L29) ``` @callback new([term()]) :: {:ok, term()} | {:error, String.t() | Exception.t()} ``` Instantiate a new function with the provided arguments [](Ash.Query.Function.html#c:partial_evaluate/1) # partial\_evaluate(func) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L33) ``` @callback partial_evaluate(func) :: {:ok, func} | {:error, term()} when func: map() ``` Evaluate a function when some or no arguments are known valid values [](Ash.Query.Function.html#c:predicate?/0) # predicate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L37) ``` @callback predicate?() :: boolean() ``` Whether or not the function is a predicate (takes a reference as the first argument, a value as the second, and returns a boolean) [](Ash.Query.Function.html#c:private?/0) # private?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L39) ``` @callback private?() :: boolean() ``` Whether or not the function should be usable when parsing input. [](Ash.Query.Function.html#c:returns/0) # returns() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L20) ``` @callback returns() :: [Ash.Type.t() | {Ash.Type.t(), constraints :: Keyword.t()}] | Ash.Type.t() | {Ash.Type.t(), constraints :: Keyword.t()} | :unknown ``` The return type for each corresponding set of args. # [](Ash.Query.Function.html#functions)Functions [](Ash.Query.Function.html#evaluate/1) # evaluate(func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L53) Evaluate the operator with provided inputs [](Ash.Query.Function.html#new/2) # new(mod, args) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L61) [](Ash.Query.Function.html#ordinal/1) # ordinal(num) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L191) Attaches the appropriate suffix to refer to an ordinal number, e.g 1 -&gt; "1st" [](Ash.Query.Function.html#try_cast_arguments/2) # try\_cast\_arguments(configured\_args, args) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/function.ex#L142) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.If (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/if.ex#L1 "View Source") If predicate is truthy, then the second argument is returned, otherwise the third. # [](Ash.Query.Function.If.html#summary)Summary ## [Functions](Ash.Query.Function.If.html#functions) [args()](Ash.Query.Function.If.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [partial\_evaluate(fun)](Ash.Query.Function.If.html#partial_evaluate/1) Callback implementation for [`Ash.Query.Function.partial_evaluate/1`](Ash.Query.Function.html#c:partial_evaluate/1). # [](Ash.Query.Function.If.html#functions)Functions [](Ash.Query.Function.If.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/if.ex#L8) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [](Ash.Query.Function.If.html#partial_evaluate/1) # partial\_evaluate(fun) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/if.ex#L52) Callback implementation for [`Ash.Query.Function.partial_evaluate/1`](Ash.Query.Function.html#c:partial_evaluate/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.IsNil (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/is_nil.ex#L1 "View Source") true if the provided field is nil # [](Ash.Query.Function.IsNil.html#summary)Summary ## [Functions](Ash.Query.Function.IsNil.html#functions) [args()](Ash.Query.Function.IsNil.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.IsNil.html#functions)Functions [](Ash.Query.Function.IsNil.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/is_nil.ex#L7) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Lazy (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/lazy.ex#L1 "View Source") Runs the provided MFA and returns the result as a known value. Evaluated just before running the query. # [](Ash.Query.Function.Lazy.html#summary)Summary ## [Functions](Ash.Query.Function.Lazy.html#functions) [args()](Ash.Query.Function.Lazy.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Lazy.html#functions)Functions [](Ash.Query.Function.Lazy.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/lazy.ex#L9) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Length (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/length.ex#L1 "View Source") Returns the length of a list attribute defined by the composite type `{:array, Type}`. ``` length(roles) ``` If the attribute allows nils: ``` length(roles || []) ``` # [](Ash.Query.Function.Length.html#summary)Summary ## [Functions](Ash.Query.Function.Length.html#functions) [args()](Ash.Query.Function.Length.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Length.html#functions)Functions [](Ash.Query.Function.Length.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/length.ex#L14) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Minus (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/minus.ex#L1 "View Source") Multiplies the value by negative one # [](Ash.Query.Function.Minus.html#summary)Summary ## [Functions](Ash.Query.Function.Minus.html#functions) [args()](Ash.Query.Function.Minus.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Minus.html#functions)Functions [](Ash.Query.Function.Minus.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/minus.ex#L7) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Now (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/now.ex#L1 "View Source") Returns the current datetime # [](Ash.Query.Function.Now.html#summary)Summary ## [Functions](Ash.Query.Function.Now.html#functions) [args()](Ash.Query.Function.Now.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Now.html#functions)Functions [](Ash.Query.Function.Now.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/now.ex#L7) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Round (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/round.ex#L1 "View Source") Rounds a float, decimal or integer to the given number of points # [](Ash.Query.Function.Round.html#summary)Summary ## [Functions](Ash.Query.Function.Round.html#functions) [args()](Ash.Query.Function.Round.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Round.html#functions)Functions [](Ash.Query.Function.Round.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/round.ex#L8) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.StartOfDay (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/start_of_day.ex#L1 "View Source") Converts a date or datetime into the start of day Accepts an optional time zone, in the same format that can be passed to [`DateTime.new/3`](../elixir/DateTime.html#new/3). For example: start\_of\_day(now()) &lt; a\_datetime() start\_of\_day(now(), "Europe/Copenhagen") &lt; a\_datetime() # [](Ash.Query.Function.StartOfDay.html#summary)Summary ## [Functions](Ash.Query.Function.StartOfDay.html#functions) [args()](Ash.Query.Function.StartOfDay.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.StartOfDay.html#functions)Functions [](Ash.Query.Function.StartOfDay.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/start_of_day.ex#L15) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.StringDowncase (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_downcase.ex#L1 "View Source") Downcase a string # [](Ash.Query.Function.StringDowncase.html#summary)Summary ## [Functions](Ash.Query.Function.StringDowncase.html#functions) [args()](Ash.Query.Function.StringDowncase.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.StringDowncase.html#functions)Functions [](Ash.Query.Function.StringDowncase.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_downcase.ex#L8) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.StringJoin (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_join.ex#L1 "View Source") Joins a list of values. Ignores `nil` values and concatenates the remaining non-nil values. An optional joiner can be provided. ``` string_join([first_name, last_name], " ") string_join([item_a, item_b]) ``` # [](Ash.Query.Function.StringJoin.html#summary)Summary ## [Functions](Ash.Query.Function.StringJoin.html#functions) [args()](Ash.Query.Function.StringJoin.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.StringJoin.html#functions)Functions [](Ash.Query.Function.StringJoin.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_join.ex#L16) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.StringLength (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_length.ex#L1 "View Source") Trims whitespace from a string # [](Ash.Query.Function.StringLength.html#summary)Summary ## [Functions](Ash.Query.Function.StringLength.html#functions) [args()](Ash.Query.Function.StringLength.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.StringLength.html#functions)Functions [](Ash.Query.Function.StringLength.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_length.ex#L8) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.StringSplit (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_split.ex#L1 "View Source") Split a string into a list of strings Splits a string on the given delimiter. The delimiter defaults to a single space. Also supports options. Keep in mind, this function does *not* support regexes the way that [`String.split/3`](../elixir/String.html#split/3) does, only raw strings. ``` string_split(employee_code) string_split(full_name, "foo") string_split(full_name, "foo", trim?: true) ``` ## [](Ash.Query.Function.StringSplit.html#module-options)Options - `:trim?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to trim empty strings from the beginning or end of the result. Equivalent to the `trim` option to [`String.split/3`](../elixir/String.html#split/3) The default value is `false`. # [](Ash.Query.Function.StringSplit.html#summary)Summary ## [Functions](Ash.Query.Function.StringSplit.html#functions) [args()](Ash.Query.Function.StringSplit.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.StringSplit.html#functions)Functions [](Ash.Query.Function.StringSplit.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_split.ex#L29) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.StringTrim (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_trim.ex#L1 "View Source") Trims whitespace from a string # [](Ash.Query.Function.StringTrim.html#summary)Summary ## [Functions](Ash.Query.Function.StringTrim.html#functions) [args()](Ash.Query.Function.StringTrim.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.StringTrim.html#functions)Functions [](Ash.Query.Function.StringTrim.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/string_trim.ex#L8) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Today (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/today.ex#L1 "View Source") Returns the current date. # [](Ash.Query.Function.Today.html#summary)Summary ## [Functions](Ash.Query.Function.Today.html#functions) [args()](Ash.Query.Function.Today.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Today.html#functions)Functions [](Ash.Query.Function.Today.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/today.ex#L8) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Function.Type (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/type.ex#L1 "View Source") Casts the value to a given type. Can also be used to provide type hints to data layers, where appropriate. # [](Ash.Query.Function.Type.html#summary)Summary ## [Functions](Ash.Query.Function.Type.html#functions) [args()](Ash.Query.Function.Type.html#args/0) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). # [](Ash.Query.Function.Type.html#functions)Functions [](Ash.Query.Function.Type.html#args/0) # args() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/type.ex#L7) Callback implementation for [`Ash.Query.Function.args/0`](Ash.Query.Function.html#c:args/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1 "View Source") A data structure for reading data from a resource. Ash queries are used for read actions and loads, and ultimately map to queries to a resource's data layer. Queries are run by calling `Ash.read`. Examples: ``` require Ash.Query MyApp.Post |> Ash.Query.filter(likes > 10) |> Ash.Query.sort([:title]) |> Ash.read!() MyApp.Author |> Ash.Query.aggregate(:published_post_count, :posts, query: [filter: [published: true]]) |> Ash.Query.sort(published_post_count: :desc) |> Ash.Query.limit(10) |> Ash.read!() MyApp.Author |> Ash.Query.load([:post_count, :comment_count]) |> Ash.Query.load(posts: [:comments]) |> Ash.read!() ``` # [](Ash.Query.html#summary)Summary ## [Types](Ash.Query.html#types) [around\_action\_fun()](Ash.Query.html#t:around_action_fun/0) [around\_callback()](Ash.Query.html#t:around_callback/0) [around\_result()](Ash.Query.html#t:around_result/0) [around\_transaction\_fun()](Ash.Query.html#t:around_transaction_fun/0) [t()](Ash.Query.html#t:t/0) ## [Functions](Ash.Query.html#functions) [accessing(query, types \\\\ \[:attributes, :relationships, :calculations, :aggregates\], only\_public? \\\\ true)](Ash.Query.html#accessing/3) Returns a list of attributes, aggregates, relationships, and calculations that are being loaded [add\_error(query, path \\\\ \[\], error)](Ash.Query.html#add_error/3) Add an error to the errors list and mark the query as invalid. [after\_action(query, func)](Ash.Query.html#after_action/2) [aggregate(query, name, kind, relationship)](Ash.Query.html#aggregate/4) Adds an aggregation to the query. [aggregate(query, name, kind, relationship, opts)](Ash.Query.html#aggregate/5) [apply\_to(query, records, opts \\\\ \[\])](Ash.Query.html#apply_to/3) [around\_transaction(query, func)](Ash.Query.html#around_transaction/2) Adds an around\_transaction hook to the query. [authorize\_results(query, func)](Ash.Query.html#authorize_results/2) [before\_action(query, func, opts \\\\ \[\])](Ash.Query.html#before_action/3) Adds a before\_action hook to the query. [build(resource, domain \\\\ nil, keyword)](Ash.Query.html#build/3) Builds a query from a keyword list. [calculate(query, name, type, module\_and\_opts, arguments \\\\ %{}, constraints \\\\ \[\], extra\_context \\\\ %{}, new\_calculation\_opts \\\\ \[\])](Ash.Query.html#calculate/8) Adds a calculation to the query. [clear\_result(query)](Ash.Query.html#clear_result/1) Removes a result set previously with [`set_result/2`](Ash.Query.html#set_result/2) [data\_layer\_query(ash\_query, opts \\\\ \[\])](Ash.Query.html#data_layer_query/2) Return the underlying data layer query for an ash query [delete\_argument(query, argument\_or\_arguments)](Ash.Query.html#delete_argument/2) Remove an argument from the query [deselect(query, fields)](Ash.Query.html#deselect/2) Ensure the the specified attributes are `nil` in the query results. [distinct(query, distincts)](Ash.Query.html#distinct/2) Get results distinct on the provided fields. [distinct\_sort(query, sorts, opts \\\\ \[\])](Ash.Query.html#distinct_sort/3) Set a sort to determine how distinct records are selected. [ensure\_selected(query, fields)](Ash.Query.html#ensure_selected/2) Ensures that the given attributes are selected. [equivalent\_to(query, expr)](Ash.Query.html#equivalent_to/2) Determines if the filter statement of a query is equivalent to the provided expression. [equivalent\_to?(query, expr)](Ash.Query.html#equivalent_to?/2) Same as [`equivalent_to/2`](Ash.Query.html#equivalent_to/2) but always returns a boolean. `:maybe` returns `false`. [fetch\_argument(query, argument)](Ash.Query.html#fetch_argument/2) fetches the value of an argument provided to the query or `:error` [filter(query, filter)](Ash.Query.html#filter/2) Attach a filter statement to the query. [filter\_input(query, filter)](Ash.Query.html#filter_input/2) Attach a filter statement to the query labelled as user input. [for\_read(query, action\_name, args \\\\ %{}, opts \\\\ \[\])](Ash.Query.html#for_read/4) Creates a query for a given read action and prepares it. [get\_argument(query, argument)](Ash.Query.html#get_argument/2) Gets the value of an argument provided to the query [limit(query, limit)](Ash.Query.html#limit/2) Limit the results returned from the query [load(query, load\_statement, opts \\\\ \[\])](Ash.Query.html#load/3) Loads relationships, calculations, or aggregates on the resource. [load\_calculation\_as(query, calc\_name, as\_name, opts\_or\_args \\\\ %{}, opts \\\\ \[\])](Ash.Query.html#load_calculation_as/5) Adds a resource calculation to the query as a custom calculation with the provided name. [load\_through(query, type, name, load)](Ash.Query.html#load_through/4) Adds a load statement to the result of an attribute or calculation. [loading?(query, item)](Ash.Query.html#loading?/2) Returns true if the field/relationship or path to field/relationship is being loaded. [lock(query, lock\_type)](Ash.Query.html#lock/2) Lock the query results. [merge\_query\_load(left, right, context)](Ash.Query.html#merge_query_load/3) Merges two query's load statements, for the purpose of handling calculation requirements. [new(resource, opts \\\\ \[\])](Ash.Query.html#new/2) Create a new query [offset(query, offset)](Ash.Query.html#offset/2) Skip the first n records [page(query, page\_opts)](Ash.Query.html#page/2) Sets the pagination options of the query. [put\_context(query, key, value)](Ash.Query.html#put_context/3) Sets a specific context key to a specific value [select(query, fields, opts \\\\ \[\])](Ash.Query.html#select/3) Ensure that only the specified *attributes* are present in the results. [selecting?(query, field)](Ash.Query.html#selecting?/2) [set\_argument(query, argument, value)](Ash.Query.html#set_argument/3) Add an argument to the query, which can be used in filter templates on actions [set\_arguments(query, map)](Ash.Query.html#set_arguments/2) Merge a map of arguments to the arguments list [set\_context(query, map)](Ash.Query.html#set_context/2) Merge a map of values into the query context [set\_domain(query, domain)](Ash.Query.html#set_domain/2) Set the query's domain, and any loaded query's domain [set\_result(query, result)](Ash.Query.html#set_result/2) Set the result of the action. This will prevent running the underlying datalayer behavior [set\_tenant(query, tenant)](Ash.Query.html#set_tenant/2) [sort(query, sorts, opts \\\\ \[\])](Ash.Query.html#sort/3) Sort the results based on attributes, aggregates or calculations. [sort\_input(query, sorts, opts \\\\ \[\])](Ash.Query.html#sort_input/3) Attach a sort statement to the query labelled as user input. [struct?(arg1)](Ash.Query.html#struct?/1) [subset\_of(query, expr)](Ash.Query.html#subset_of/2) Determines if the provided expression would return data that is a suprset of the data returned by the filter on the query. [subset\_of?(query, expr)](Ash.Query.html#subset_of?/2) Same as [`subset_of/2`](Ash.Query.html#subset_of/2) but always returns a boolean. `:maybe` returns `false`. [superset\_of(query, expr)](Ash.Query.html#superset_of/2) Determines if the provided expression would return data that is a subset of the data returned by the filter on the query. [superset\_of?(query, expr)](Ash.Query.html#superset_of?/2) Same as [`superset_of/2`](Ash.Query.html#superset_of/2) but always returns a boolean. `:maybe` returns `false`. [timeout(query, timeout)](Ash.Query.html#timeout/2) [unload(query, fields)](Ash.Query.html#unload/2) Removes a field from the list of fields to load [unset(query, keys)](Ash.Query.html#unset/2) # [](Ash.Query.html#types)Types [](Ash.Query.html#t:around_action_fun/0) # around\_action\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L111) ``` @type around_action_fun() :: (t(), around_callback() -> around_result()) ``` [](Ash.Query.html#t:around_callback/0) # around\_callback() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L110) ``` @type around_callback() :: (t() -> around_result()) ``` [](Ash.Query.html#t:around_result/0) # around\_result() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L107) ``` @type around_result() :: {:ok, [Ash.Resource.record()]} | {:error, Ash.Error.t()} ``` [](Ash.Query.html#t:around_transaction_fun/0) # around\_transaction\_fun() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L113) ``` @type around_transaction_fun() :: (t() -> {:ok, Ash.Resource.record()} | {:error, any()}) ``` [](Ash.Query.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L69) ``` @type t() :: %Ash.Query{ __validated_for_action__: atom() | nil, action: Ash.Resource.Actions.Read.t() | nil, action_failed?: boolean(), after_action: [ (t(), [Ash.Resource.record()] -> {:ok, [Ash.Resource.record()]} | {:ok, [Ash.Resource.record()], [Ash.Notifier.Notification.t()]} | {:error, any()}) ], aggregates: %{optional(atom()) => Ash.Filter.t()}, arguments: %{optional(atom()) => any()}, around_transaction: term(), authorize_results: [ (t(), [Ash.Resource.record()] -> {:ok, [Ash.Resource.record()]} | {:error, any()}) ], before_action: [(t() -> t())], calculations: %{optional(atom()) => :wat}, context: map(), distinct: [atom()], distinct_sort: term(), domain: module() | nil, errors: [Ash.Error.t()], filter: Ash.Filter.t() | nil, invalid_keys: term(), limit: nil | non_neg_integer(), load: keyword(keyword()), load_through: term(), lock: term(), offset: non_neg_integer(), page: keyword() | nil, params: %{optional(atom() | binary()) => any()}, phase: :preparing | :before_action | :after_action | :executing, resource: module(), select: nil | [atom()], sort: [atom() | {atom(), :asc | :desc}], sort_input_indices: term(), tenant: term(), timeout: pos_integer() | nil, to_tenant: term(), valid?: boolean() } ``` # [](Ash.Query.html#functions)Functions [](Ash.Query.html#accessing/3) # accessing(query, types \\\\ \[:attributes, :relationships, :calculations, :aggregates], only\_public? \\\\ true) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1098) Returns a list of attributes, aggregates, relationships, and calculations that are being loaded Provide a list of field types to narrow down the returned results. [](Ash.Query.html#add_error/3) # add\_error(query, path \\\\ \[], error) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L3105) ``` @spec add_error(t(), path :: Ash.Error.path_input(), Ash.Error.error_input()) :: t() ``` Add an error to the errors list and mark the query as invalid. See [`Ash.Error.to_ash_error/3`](Ash.Error.html#to_ash_error/3) for more on supported values for `error` ## [](Ash.Query.html#add_error/3-inconsistencies)Inconsistencies The `path` argument is the second argument here, but the third argument in [`Ash.ActionInput.add_error/2`](Ash.ActionInput.html#add_error/2) and [`Ash.Changeset.add_error/2`](Ash.Changeset.html#add_error/2). This will be fixed in 4.0. [](Ash.Query.html#after_action/2) # after\_action(query, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L861) ``` @spec after_action( t(), (t(), [Ash.Resource.record()] -> {:ok, [Ash.Resource.record()]} | {:ok, [Ash.Resource.record()], [Ash.Notifier.Notification.t()]} | {:error, term()}) ) :: t() ``` [](Ash.Query.html#aggregate/4) # aggregate(query, name, kind, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2330) Adds an aggregation to the query. Aggregations are made available on the `aggregates` field of the records returned The filter option accepts either a filter or a keyword list of options to supply to build a limiting query for that aggregate. See the DSL docs for each aggregate type in the [Resource DSL docs](dsl-ash-resource.html#aggregates) for more information. Options: - query: The query over the destination resource to use as a base for aggregation - default: The default value to use if the aggregate returns nil - filterable?: Whether or not this aggregate may be referenced in filters - type: The type of the aggregate - constraints: Type constraints for the aggregate's type - implementation: An implementation used when the aggregate kind is custom - read\_action: The read action to use on the destination resource - authorize?: Whether or not to authorize access to this aggregate - join\_filters: A map of relationship paths to filter expressions. See the aggregates guide for more. [](Ash.Query.html#aggregate/5) # aggregate(query, name, kind, relationship, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2334) [](Ash.Query.html#apply_to/3) # apply\_to(query, records, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2938) ``` @spec apply_to(t(), records :: [Ash.Resource.record()], opts :: Keyword.t()) :: {:ok, [Ash.Resource.record()]} ``` [](Ash.Query.html#around_transaction/2) # around\_transaction(query, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L815) ``` @spec around_transaction(t(), around_transaction_fun()) :: t() ``` Adds an around\_transaction hook to the query. Your function will get the query, and a callback that must be called with a query (that may be modified). The callback will return `{:ok, results}` or `{:error, error}`. You can modify these values, but the return value must be one of those types. The around\_transaction calls happen first, and then (after they each resolve their callbacks) the `before_action` hooks are called, followed by the `after_action` hooks being run. Then, the code that appeared *after* the callbacks were called is then run. Warning: using this without understanding how it works can cause big problems. You *must* call the callback function that is provided to your hook, and the return value must contain the same structure that was given to you, i.e `{:ok, result_of_action}`. [](Ash.Query.html#authorize_results/2) # authorize\_results(query, func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L849) ``` @spec authorize_results( t(), (t(), [Ash.Resource.record()] -> {:ok, [Ash.Resource.record()]} | {:ok, [Ash.Resource.record()], [Ash.Notifier.Notification.t()]} | {:error, term()}) ) :: t() ``` [](Ash.Query.html#before_action/3) # before\_action(query, func, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L832) ``` @spec before_action( query :: t(), fun :: (t() -> t() | {t(), [Ash.Notifier.Notification.t()]}), opts :: Keyword.t() ) :: t() ``` Adds a before\_action hook to the query. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. [](Ash.Query.html#build/3) # build(resource, domain \\\\ nil, keyword) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2235) ``` @spec build(Ash.Resource.t() | t(), Ash.Domain.t() | nil, Keyword.t()) :: t() ``` Builds a query from a keyword list. This is used by certain query constructs like aggregates. It can also be used to manipulate a data structure before passing it to an ash query. It allows for building an entire query struct using only a keyword list. For example: ``` Ash.Query.build(MyResource, filter: [name: "fred"], sort: [name: :asc], load: [:foo, :bar], offset: 10) ``` If you want to use the expression style filters, you can use `expr/1`. For example: ``` import Ash.Expr, only: [expr: 1] Ash.Query.build(Myresource, filter: expr(name == "marge")) ``` ## [](Ash.Query.html#build/3-options)Options - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter keyword, map or expression - `:filter_input` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter keyword or map, provided as input from an external source - `:sort` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A sort list or keyword - `:sort_input` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A sort list or keyword, provided as input from an external source - `:distinct_sort` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A distinct\_sort list or keyword - `:limit` ([`integer/0`](../elixir/typespecs.html#basic-types)) - A limit to apply - `:offset` ([`integer/0`](../elixir/typespecs.html#basic-types)) - An offset to apply - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add to the query - `:select` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A select statement to add to the query - `:ensure_selected` ([`term/0`](../elixir/typespecs.html#built-in-types)) - An ensure\_selected statement to add to the query - `:aggregate` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A custom aggregate to add to the query. Can be `{name, type, relationship}` or `{name, type, relationship, build_opts}` - `:calculate` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A custom calculation to add to the query. Can be `{name, module_and_opts}` or `{name, module_and_opts, context}` - `:distinct` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A distinct clause to add to the query - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - A map to merge into the query context [](Ash.Query.html#calculate/8) # calculate(query, name, type, module\_and\_opts, arguments \\\\ %{}, constraints \\\\ \[], extra\_context \\\\ %{}, new\_calculation\_opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2428) Adds a calculation to the query. Calculations are made available on the `calculations` field of the records returned The `module_and_opts` argument accepts either a `module` or a `{module, opts}`. For more information on what that module should look like, see [`Ash.Resource.Calculation`](Ash.Resource.Calculation.html). [](Ash.Query.html#clear_result/1) # clear\_result(query) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1885) ``` @spec clear_result(t()) :: t() ``` Removes a result set previously with [`set_result/2`](Ash.Query.html#set_result/2) [](Ash.Query.html#data_layer_query/2) # data\_layer\_query(ash\_query, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L3007) Return the underlying data layer query for an ash query [](Ash.Query.html#delete_argument/2) # delete\_argument(query, argument\_or\_arguments) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2009) Remove an argument from the query [](Ash.Query.html#deselect/2) # deselect(query, fields) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1119) Ensure the the specified attributes are `nil` in the query results. [](Ash.Query.html#distinct/2) # distinct(query, distincts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2877) ``` @spec distinct(t() | Ash.Resource.t(), Ash.Sort.t()) :: t() ``` Get results distinct on the provided fields. Takes a list of fields to distinct on. Each call is additive, so to remove the `distinct` use [`unset/2`](Ash.Query.html#unset/2). Examples: ``` Ash.Query.distinct(query, [:first_name, :last_name]) Ash.Query.distinct(query, :email) ``` [](Ash.Query.html#distinct_sort/3) # distinct\_sort(query, sorts, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2904) Set a sort to determine how distinct records are selected. If none is set, any sort applied to the query will be used. This is useful if you want to control how the `distinct` records are selected without affecting (necessarily, it may affect it if there is no sort applied) the overall sort of the query [](Ash.Query.html#ensure_selected/2) # ensure\_selected(query, fields) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1079) Ensures that the given attributes are selected. The first call to [`select/2`](Ash.Query.html#select/2) will *limit* the fields to only the provided fields. Use [`ensure_selected/2`](Ash.Query.html#ensure_selected/2) to say "select this field (or these fields) without deselecting anything else". See [`select/2`](Ash.Query.html#select/2) for more. [](Ash.Query.html#equivalent_to/2) # equivalent\_to(query, expr) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L949) Determines if the filter statement of a query is equivalent to the provided expression. This uses the satisfiability solver that is used when solving for policy authorizations. In complex scenarios, or when using custom database expressions, (like fragments in ash\_postgres), this function may return `:maybe`. Use `supserset_of?` to always return a boolean. [](Ash.Query.html#equivalent_to?/2) # equivalent\_to?(query, expr) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L972) Same as [`equivalent_to/2`](Ash.Query.html#equivalent_to/2) but always returns a boolean. `:maybe` returns `false`. [](Ash.Query.html#fetch_argument/2) # fetch\_argument(query, argument) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1912) ``` @spec fetch_argument(t(), atom()) :: {:ok, term()} | :error ``` fetches the value of an argument provided to the query or `:error` [](Ash.Query.html#filter/2) # filter(query, filter) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L382) Attach a filter statement to the query. The filter is applied as an "and" to any filters currently on the query. For more information on writing filters, see: [`Ash.Filter`](Ash.Filter.html). [](Ash.Query.html#filter_input/2) # filter\_input(query, filter) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L283) Attach a filter statement to the query labelled as user input. Filters added as user input (or filters constructed with `Ash.Filter.parse_input`) will honor any field policies on resources by replacing any references to the field with `nil` in cases where the actor should not be able to see the given field. This function does not expect the expression style filter (because an external source could never reasonably provide that). Instead, use the keyword/map style syntax. For example: `expr(name == "fred")` could be any of - map syntax: `%{"name" => %{"eq" => "fred"}}` - keyword syntax: `[name: [eq: "fred"]]` See [`Ash.Filter`](Ash.Filter.html) for more. [](Ash.Query.html#for_read/4) # for\_read(query, action\_name, args \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L526) Creates a query for a given read action and prepares it. Multitenancy is *not* validated until an action is called. This allows you to avoid specifying a tenant until just before calling the domain action. ### [](Ash.Query.html#for_read/4-arguments)Arguments Provide a map or keyword list of arguments for the read action ### [](Ash.Query.html#for_read/4-opts)Opts - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - set the actor, which can be used in any [`Ash.Resource.Change`](Ash.Resource.Change.html)s configured on the action. (in the `context` argument) - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - set authorize?, which can be used in any [`Ash.Resource.Change`](Ash.Resource.Change.html)s configured on the action. (in the `context` argument) - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer to use. Will be carried over to the action. For more information see [`Ash.Tracer`](Ash.Tracer.html). - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - set the tenant on the query - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to apply to the query - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - A map of context to set on the query. This will be merged with any context set on the query itself. [](Ash.Query.html#get_argument/2) # get\_argument(query, argument) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1906) ``` @spec get_argument(t(), atom()) :: term() ``` Gets the value of an argument provided to the query [](Ash.Query.html#limit/2) # limit(query, limit) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2523) ``` @spec limit(t() | Ash.Resource.t(), nil | integer()) :: t() ``` Limit the results returned from the query [](Ash.Query.html#load/3) # load(query, load\_statement, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1355) ``` @spec load( t() | Ash.Resource.t(), atom() | Ash.Query.Calculation.t() | Ash.Query.Aggregate.t() | [atom() | Ash.Query.Calculation.t() | Ash.Query.Aggregate.t()] | [{atom() | Ash.Query.Calculation.t() | Ash.Query.Aggregate.t(), term()}], Keyword.t() ) :: t() ``` Loads relationships, calculations, or aggregates on the resource. By default, loading attributes has no effects, as all attributes are returned. ``` # Loading nested relationships Ash.Query.load(query, [comments: [:author, :ratings]]) # Loading relationships with a query Ash.Query.load(query, [comments: [author: author_query]]) ``` By passing the `strict?: true` option, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. The select statement of any queries inside the load statement will not be affected. Example: ``` Ash.load(category, [:name, posts: [:title, :published_at]], strict?: true) ``` Here, the only fields that will be loaded on the `posts` relationship are `title` and `published_at`, in addition to any other fields that are required to be loaded, like the primary and relevant foreign keys. This entails that when using `strict?: true` and loading nested relationships, you will also always have to specify all the attributes you want to load alongside the nested relationships. Example: ``` Ash.load(post, [:title, :published_at, :other_needed_attribute, category: [:name]], strict?: true) ``` If no fields are specified on a relationship when using `strict?: true`, all attributes will be loaded by default. Example: ``` Ash.load(category, [:name, :posts], strict?: true) ``` [](Ash.Query.html#load_calculation_as/5) # load\_calculation\_as(query, calc\_name, as\_name, opts\_or\_args \\\\ %{}, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2498) Adds a resource calculation to the query as a custom calculation with the provided name. Example: ``` Ash.Query.load_calculation_as(query, :calculation, :some_name, args: %{}, load_through: [:foo]) ``` [](Ash.Query.html#load_through/4) # load\_through(query, type, name, load) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1240) Adds a load statement to the result of an attribute or calculation. Uses [`Ash.Type.load/5`](Ash.Type.html#load/5) to request that the type load nested data. [](Ash.Query.html#loading?/2) # loading?(query, item) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1172) Returns true if the field/relationship or path to field/relationship is being loaded. It accepts an atom or a list of atoms, which is treated for as a "path", i.e: ``` Resource |> Ash.Query.load(friends: [enemies: [:score]]) |> Ash.Query.loading?([:friends, :enemies, :score]) iex> true Resource |> Ash.Query.load(friends: [enemies: [:score]]) |> Ash.Query.loading?([:friends, :score]) iex> false Resource |> Ash.Query.load(friends: [enemies: [:score]]) |> Ash.Query.loading?(:friends) iex> true ``` [](Ash.Query.html#lock/2) # lock(query, lock\_type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2782) ``` @spec lock(t() | Ash.Resource.t(), Ash.DataLayer.lock_type()) :: t() ``` Lock the query results. This must be run while in a transaction, and is not supported by all data layers. [](Ash.Query.html#merge_query_load/3) # merge\_query\_load(left, right, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1282) Merges two query's load statements, for the purpose of handling calculation requirements. This should only be used if you are writing a custom type that is loadable. See the callback documentation for [`Ash.Type.merge_load/4`](Ash.Type.html#c:merge_load/4) for more. [](Ash.Query.html#new/2) # new(resource, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L420) ``` @spec new(Ash.Resource.t() | t(), opts :: Keyword.t()) :: t() ``` Create a new query [](Ash.Query.html#offset/2) # offset(query, offset) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2542) ``` @spec offset(t() | Ash.Resource.t(), nil | integer()) :: t() ``` Skip the first n records [](Ash.Query.html#page/2) # page(query, page\_opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2051) ``` @spec page(t() | Ash.Resource.t(), Keyword.t() | nil | false) :: t() ``` Sets the pagination options of the query. Pass `nil` to disable pagination. ### [](Ash.Query.html#page/2-limit-offset-pagination)Limit/offset pagination - `:offset` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to skip from the beginning of the query - `:limit` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in the page - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter to apply for pagination purposes, that should not be considered in the full count. This is used by the liveview paginator to only fetch the records that were *already* on the page when refreshing data, to avoid pages jittering. - `:count` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return the page with a full count of all records ### [](Ash.Query.html#page/2-keyset-pagination)Keyset pagination - `:before` ([`String.t/0`](../elixir/String.html#t:t/0)) - Get records that appear before the provided keyset (mutually exclusive with `after`) - `:after` ([`String.t/0`](../elixir/String.html#t:t/0)) - Get records that appear after the provided keyset (mutually exclusive with `before`) - `:limit` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - How many records to include in the page - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - See the `filter` option for offset pagination, this behaves the same. - `:count` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return the page with a full count of all records [](Ash.Query.html#put_context/3) # put\_context(query, key, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1868) ``` @spec put_context(t() | Ash.Resource.t(), atom(), term()) :: t() ``` Sets a specific context key to a specific value See [`set_context/2`](Ash.Query.html#set_context/2) for more information. [](Ash.Query.html#select/3) # select(query, fields, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L902) Ensure that only the specified *attributes* are present in the results. The first call to [`select/2`](Ash.Query.html#select/2) will replace the default behavior of selecting all attributes. Subsequent calls to [`select/2`](Ash.Query.html#select/2) will combine the provided fields unless the `replace?` option is provided with a value of `true`. If a field has been deselected, selecting it again will override that (because a single list of fields is tracked for selection) Primary key attributes are always selected and cannot be deselected. When attempting to load a relationship (or manage it with [`Ash.Changeset.manage_relationship/3`](Ash.Changeset.html#manage_relationship/3)), if the source field is not selected on the query/provided data an error will be produced. If loading a relationship with a query, an error is produced if the query does not select the destination field of the relationship. Use [`ensure_selected/2`](Ash.Query.html#ensure_selected/2) if you wish to make sure a field has been selected, without deselecting any other fields. [](Ash.Query.html#selecting?/2) # selecting?(query, field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1137) [](Ash.Query.html#set_argument/3) # set\_argument(query, argument, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1928) Add an argument to the query, which can be used in filter templates on actions [](Ash.Query.html#set_arguments/2) # set\_arguments(query, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2022) Merge a map of arguments to the arguments list [](Ash.Query.html#set_context/2) # set\_context(query, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1896) ``` @spec set_context(t() | Ash.Resource.t(), map() | nil) :: t() ``` Merge a map of values into the query context [](Ash.Query.html#set_domain/2) # set\_domain(query, domain) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2305) Set the query's domain, and any loaded query's domain [](Ash.Query.html#set_result/2) # set\_result(query, result) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1877) ``` @spec set_result(t(), term()) :: t() ``` Set the result of the action. This will prevent running the underlying datalayer behavior [](Ash.Query.html#set_tenant/2) # set\_tenant(query, tenant) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2034) ``` @spec set_tenant(t() | Ash.Resource.t(), Ash.ToTenant.t()) :: t() ``` [](Ash.Query.html#sort/3) # sort(query, sorts, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2825) ``` @spec sort(t() | Ash.Resource.t(), Ash.Sort.t(), opts :: Keyword.t()) :: t() ``` Sort the results based on attributes, aggregates or calculations. Calculations are supported if they are defined with expressions, which can be done one of two ways. 1. with the shorthand `calculate :calc, :type, expr(a + b)` 2. By defining `expression/2` in a custom calculation module See the guide on calculations for more. Takes a list of fields to sort on, or a keyword list/mixed keyword list of fields and sort directions. The default sort direction is `:asc`. Examples: ``` Ash.Query.sort(query, [:foo, :bar]) Ash.Query.sort(query, [:foo, bar: :desc]) Ash.Query.sort(query, [foo: :desc, bar: :asc]) ``` ## [](Ash.Query.html#sort/3-options)Options - `prepend?` - set to `true` to put your sort at the front of the list of a sort is already specified [](Ash.Query.html#sort_input/3) # sort\_input(query, sorts, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L302) Attach a sort statement to the query labelled as user input. Sorts added as user input (or filters constructed with `Ash.Filter.parse_input`) will honor any field policies on resources by replacing any references to the field with `nil` in cases where the actor should not be able to see the given field. [](Ash.Query.html#struct?/1) # struct?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2030) [](Ash.Query.html#subset_of/2) # subset\_of(query, expr) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1032) Determines if the provided expression would return data that is a suprset of the data returned by the filter on the query. This uses the satisfiability solver that is used when solving for policy authorizations. In complex scenarios, or when using custom database expressions, (like fragments in ash\_postgres), this function may return `:maybe`. Use `subset_of?` to always return a boolean. [](Ash.Query.html#subset_of?/2) # subset\_of?(query, expr) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1065) Same as [`subset_of/2`](Ash.Query.html#subset_of/2) but always returns a boolean. `:maybe` returns `false`. [](Ash.Query.html#superset_of/2) # superset\_of(query, expr) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L985) Determines if the provided expression would return data that is a subset of the data returned by the filter on the query. This uses the satisfiability solver that is used when solving for policy authorizations. In complex scenarios, or when using custom database expressions, (like fragments in ash\_postgres), this function may return `:maybe`. Use `supserset_of?` to always return a boolean. [](Ash.Query.html#superset_of?/2) # superset\_of?(query, expr) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L1019) Same as [`superset_of/2`](Ash.Query.html#superset_of/2) but always returns a boolean. `:maybe` returns `false`. [](Ash.Query.html#timeout/2) # timeout(query, timeout) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L603) [](Ash.Query.html#unload/2) # unload(query, fields) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2062) ``` @spec unload(t(), [atom()]) :: t() ``` Removes a field from the list of fields to load [](Ash.Query.html#unset/2) # unset(query, keys) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/query.ex#L2968) ``` @spec unset(Ash.Resource.t() | t(), atom() | [atom()]) :: t() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Not (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/not.ex#L1 "View Source") Represents the negation of the contained expression # [](Ash.Query.Not.html#summary)Summary ## [Functions](Ash.Query.Not.html#functions) [new(expression)](Ash.Query.Not.html#new/1) # [](Ash.Query.Not.html#functions)Functions [](Ash.Query.Not.html#new/1) # new(expression) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/not.ex#L5) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.Eq (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/eq.ex#L1 "View Source") left == right The simplest operator, matches if the left and right are equal. For comparison, this compares as mutually exclusive with other equality and `is_nil` checks that have the same reference on the left side # [](Ash.Query.Operator.Eq.html#summary)Summary ## [Functions](Ash.Query.Operator.Eq.html#functions) [evaluate(map)](Ash.Query.Operator.Eq.html#evaluate/1) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [name()](Ash.Query.Operator.Eq.html#name/0) [operator()](Ash.Query.Operator.Eq.html#operator/0) # [](Ash.Query.Operator.Eq.html#functions)Functions [](Ash.Query.Operator.Eq.html#evaluate/1) # evaluate(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/eq.ex#L20) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [](Ash.Query.Operator.Eq.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/eq.ex#L10) [](Ash.Query.Operator.Eq.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/eq.ex#L10) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.GreaterThan (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than.ex#L1 "View Source") left &gt; right In comparison, simplifies to `not(left < right + 1)`, so it will never need to be compared against. # [](Ash.Query.Operator.GreaterThan.html#summary)Summary ## [Functions](Ash.Query.Operator.GreaterThan.html#functions) [evaluate(map)](Ash.Query.Operator.GreaterThan.html#evaluate/1) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [name()](Ash.Query.Operator.GreaterThan.html#name/0) [operator()](Ash.Query.Operator.GreaterThan.html#operator/0) # [](Ash.Query.Operator.GreaterThan.html#functions)Functions [](Ash.Query.Operator.GreaterThan.html#evaluate/1) # evaluate(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than.ex#L13) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [](Ash.Query.Operator.GreaterThan.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than.ex#L7) [](Ash.Query.Operator.GreaterThan.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than.ex#L7) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.GreaterThanOrEqual (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than_or_equal.ex#L1 "View Source") left &gt;= right In comparison, simplifies to `not(left < right)`, so it will never need to be compared against. # [](Ash.Query.Operator.GreaterThanOrEqual.html#summary)Summary ## [Functions](Ash.Query.Operator.GreaterThanOrEqual.html#functions) [evaluate(map)](Ash.Query.Operator.GreaterThanOrEqual.html#evaluate/1) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [name()](Ash.Query.Operator.GreaterThanOrEqual.html#name/0) [operator()](Ash.Query.Operator.GreaterThanOrEqual.html#operator/0) # [](Ash.Query.Operator.GreaterThanOrEqual.html#functions)Functions [](Ash.Query.Operator.GreaterThanOrEqual.html#evaluate/1) # evaluate(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than_or_equal.ex#L13) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [](Ash.Query.Operator.GreaterThanOrEqual.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than_or_equal.ex#L7) [](Ash.Query.Operator.GreaterThanOrEqual.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/greater_than_or_equal.ex#L7) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L1 "View Source") An operator is a predicate with a `left` and a `right` For more information on being a predicate, see [`Ash.Filter.Predicate`](Ash.Filter.Predicate.html). Most of the complexities are there. An operator must meet both behaviours. # [](Ash.Query.Operator.html#summary)Summary ## [Callbacks](Ash.Query.Operator.html#callbacks) [can\_return\_nil?(func)](Ash.Query.Operator.html#c:can_return_nil?/1) Whether or not the operator can evaluate to nil. [evaluate(term)](Ash.Query.Operator.html#c:evaluate/1) Evaluates the operator in Elixir [evaluate\_nil\_inputs?()](Ash.Query.Operator.html#c:evaluate_nil_inputs?/0) If `true`, will be allowed to evaluate `nil` inputs. [new(term, term)](Ash.Query.Operator.html#c:new/2) Create a new predicate. There are various return types possible [predicate?()](Ash.Query.Operator.html#c:predicate?/0) [returns()](Ash.Query.Operator.html#c:returns/0) The types that the expression can return. Should be one entry in the list for each entry in `types`. [to\_string(struct, t)](Ash.Query.Operator.html#c:to_string/2) The implementation of the inspect protocol. [types()](Ash.Query.Operator.html#c:types/0) The types accepted by the operator. Defaults to `[:same, :any]`, which is any values of the same type. ## [Functions](Ash.Query.Operator.html#functions) [evaluate(op)](Ash.Query.Operator.html#evaluate/1) Evaluate the operator with provided inputs [new(mod, left, right)](Ash.Query.Operator.html#new/3) Create a new operator. Pass the module and the left and right values [operator\_overloads(operator)](Ash.Query.Operator.html#operator_overloads/1) Get type overloads for the given operator [operator\_symbols()](Ash.Query.Operator.html#operator_symbols/0) [operators()](Ash.Query.Operator.html#operators/0) # [](Ash.Query.Operator.html#callbacks)Callbacks [](Ash.Query.Operator.html#c:can_return_nil?/1) # can\_return\_nil?(func) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L60) ``` @callback can_return_nil?(func :: map()) :: boolean() ``` Whether or not the operator can evaluate to nil. [](Ash.Query.Operator.html#c:evaluate/1) # evaluate(term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L32) ``` @callback evaluate(term()) :: term() ``` Evaluates the operator in Elixir [](Ash.Query.Operator.html#c:evaluate_nil_inputs?/0) # evaluate\_nil\_inputs?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L39) ``` @callback evaluate_nil_inputs?() :: boolean() ``` If `true`, will be allowed to evaluate `nil` inputs. If `false` (the default), any `nil` inputs will cause a `nil` return. [](Ash.Query.Operator.html#c:new/2) # new(term, term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L19) ``` @callback new(term(), term()) :: {:ok, term(), term()} | {:ok, term()} | {:known, boolean()} | {:error, term()} ``` Create a new predicate. There are various return types possible: - `{:ok, left, right}` - Return the left/right values of the operator - `{:ok, operator}` - Return the operator itself, this or the one above are acceptable - `{:known, boolean}` - If the value is already known, e.g `1 == 1` - `{:error, error}` - If there was an error creating the operator [](Ash.Query.Operator.html#c:predicate?/0) # predicate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L55) ``` @callback predicate?() :: boolean() ``` [](Ash.Query.Operator.html#c:returns/0) # returns() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L51) ``` @callback returns() :: [ :any | :same | Ash.Type.t() | {Ash.Type.t(), constraints :: Keyword.t()} ] ``` The types that the expression can return. Should be one entry in the list for each entry in `types`. [](Ash.Query.Operator.html#c:to_string/2) # to\_string(struct, t) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L27) ``` @callback to_string( struct(), Inspect.Opts.t() ) :: term() ``` The implementation of the inspect protocol. If not defined, it will be inferred [](Ash.Query.Operator.html#c:types/0) # types() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L44) ``` @callback types() :: [ :any | :same | [Ash.Type.t() | {Ash.Type.t(), constraints :: Keyword.t()}] ] ``` The types accepted by the operator. Defaults to `[:same, :any]`, which is any values of the same type. # [](Ash.Query.Operator.html#functions)Functions [](Ash.Query.Operator.html#evaluate/1) # evaluate(op) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L63) Evaluate the operator with provided inputs [](Ash.Query.Operator.html#new/3) # new(mod, left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L106) Create a new operator. Pass the module and the left and right values [](Ash.Query.Operator.html#operator_overloads/1) # operator\_overloads(operator) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L157) Get type overloads for the given operator [](Ash.Query.Operator.html#operator_symbols/0) # operator\_symbols() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L383) [](Ash.Query.Operator.html#operators/0) # operators() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/operator.ex#L370) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.In (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/in.ex#L1 "View Source") left in \[1, 2, 3] this predicate matches if the left is in the list on the right For comparison, this simplifies to a set of "or equals", e.g `{:or, {:or, {:or, left == 1}, left == 2}, left == 3}` # [](Ash.Query.Operator.In.html#summary)Summary ## [Functions](Ash.Query.Operator.In.html#functions) [evaluate(map)](Ash.Query.Operator.In.html#evaluate/1) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [name()](Ash.Query.Operator.In.html#name/0) [operator()](Ash.Query.Operator.In.html#operator/0) # [](Ash.Query.Operator.In.html#functions)Functions [](Ash.Query.Operator.In.html#evaluate/1) # evaluate(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/in.ex#L26) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [](Ash.Query.Operator.In.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/in.ex#L10) [](Ash.Query.Operator.In.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/in.ex#L10) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.IsNil (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/is_nil.ex#L1 "View Source") left is\_nil true/false This predicate matches if the left is nil when the right is `true` or if the left is not nil when the right is `false` # [](Ash.Query.Operator.IsNil.html#summary)Summary ## [Functions](Ash.Query.Operator.IsNil.html#functions) [name()](Ash.Query.Operator.IsNil.html#name/0) [operator()](Ash.Query.Operator.IsNil.html#operator/0) # [](Ash.Query.Operator.IsNil.html#functions)Functions [](Ash.Query.Operator.IsNil.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/is_nil.ex#L8) [](Ash.Query.Operator.IsNil.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/is_nil.ex#L8) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.LessThan (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than.ex#L1 "View Source") left &lt; right Does not simplify, but is used as the simplification value for [`Ash.Query.Operator.LessThanOrEqual`](Ash.Query.Operator.LessThanOrEqual.html), [`Ash.Query.Operator.GreaterThan`](Ash.Query.Operator.GreaterThan.html) and [`Ash.Query.Operator.GreaterThanOrEqual`](Ash.Query.Operator.GreaterThanOrEqual.html). When comparing predicates, it is mutually exclusive with [`Ash.Query.Operator.IsNil`](Ash.Query.Operator.IsNil.html). Additionally, it compares as mutually inclusive with any [`Ash.Query.Operator.Eq`](Ash.Query.Operator.Eq.html) and any [`Ash.Query.Operator.LessThan`](Ash.Query.Operator.LessThan.html) who's right sides are less than it, and mutually exclusive with any [`Ash.Query.Operator.Eq`](Ash.Query.Operator.Eq.html) or [`Ash.Query.Operator.GreaterThan`](Ash.Query.Operator.GreaterThan.html) who's right side's are greater than or equal to it. # [](Ash.Query.Operator.LessThan.html#summary)Summary ## [Functions](Ash.Query.Operator.LessThan.html#functions) [evaluate(map)](Ash.Query.Operator.LessThan.html#evaluate/1) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [name()](Ash.Query.Operator.LessThan.html#name/0) [operator()](Ash.Query.Operator.LessThan.html#operator/0) # [](Ash.Query.Operator.LessThan.html#functions)Functions [](Ash.Query.Operator.LessThan.html#evaluate/1) # evaluate(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than.ex#L24) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [](Ash.Query.Operator.LessThan.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than.ex#L16) [](Ash.Query.Operator.LessThan.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than.ex#L16) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.LessThanOrEqual (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than_or_equal.ex#L1 "View Source") left &lt;= right In comparison, simplifies to `left < right + 1`, so it will never need to be compared against. # [](Ash.Query.Operator.LessThanOrEqual.html#summary)Summary ## [Functions](Ash.Query.Operator.LessThanOrEqual.html#functions) [evaluate(map)](Ash.Query.Operator.LessThanOrEqual.html#evaluate/1) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [name()](Ash.Query.Operator.LessThanOrEqual.html#name/0) [operator()](Ash.Query.Operator.LessThanOrEqual.html#operator/0) # [](Ash.Query.Operator.LessThanOrEqual.html#functions)Functions [](Ash.Query.Operator.LessThanOrEqual.html#evaluate/1) # evaluate(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than_or_equal.ex#L13) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [](Ash.Query.Operator.LessThanOrEqual.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than_or_equal.ex#L7) [](Ash.Query.Operator.LessThanOrEqual.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/less_than_or_equal.ex#L7) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Operator.NotEq (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/not_eq.ex#L1 "View Source") left != right In comparison, simplifies to `not(left == right)` # [](Ash.Query.Operator.NotEq.html#summary)Summary ## [Functions](Ash.Query.Operator.NotEq.html#functions) [evaluate(map)](Ash.Query.Operator.NotEq.html#evaluate/1) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [name()](Ash.Query.Operator.NotEq.html#name/0) [operator()](Ash.Query.Operator.NotEq.html#operator/0) # [](Ash.Query.Operator.NotEq.html#functions)Functions [](Ash.Query.Operator.NotEq.html#evaluate/1) # evaluate(map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/not_eq.ex#L16) Callback implementation for [`Ash.Query.Operator.evaluate/1`](Ash.Query.Operator.html#c:evaluate/1). [](Ash.Query.Operator.NotEq.html#name/0) # name() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/not_eq.ex#L7) [](Ash.Query.Operator.NotEq.html#operator/0) # operator() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/operator/not_eq.ex#L7) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Parent (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/parent.ex#L1 "View Source") Used to access values from the "source" of a given expression. This is used in cases where expressions are given for some relationship path, for example:any() ``` has_many :foo, Foo do filter expr(priority == :foo and type == parent(foo_type)) end ``` This is supported on a case by case basis by a given data layer and in specific usages. # [](Ash.Query.Parent.html#summary)Summary ## [Functions](Ash.Query.Parent.html#functions) [new(expr)](Ash.Query.Parent.html#new/1) # [](Ash.Query.Parent.html#functions)Functions [](Ash.Query.Parent.html#new/1) # new(expr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/parent.ex#L18) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.Ref (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/ref.ex#L1 "View Source") Represents a relation/attribute reference # [](Ash.Query.Ref.html#summary)Summary ## [Functions](Ash.Query.Ref.html#functions) [name(ref)](Ash.Query.Ref.html#name/1) Returns the referenced field # [](Ash.Query.Ref.html#functions)Functions [](Ash.Query.Ref.html#name/1) # name(ref) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/ref.ex#L6) Returns the referenced field [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Query.UpsertConflict (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/upsert_conflict.ex#L1 "View Source") Returns the conflicting new information. # [](Ash.Query.UpsertConflict.html#summary)Summary ## [Functions](Ash.Query.UpsertConflict.html#functions) [new(attribute)](Ash.Query.UpsertConflict.html#new/1) # [](Ash.Query.UpsertConflict.html#functions)Functions [](Ash.Query.UpsertConflict.html#new/1) # new(attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/query/function/upsert_conflict.ex#L8) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.ActionStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/action_step.ex#L1 "View Source") The Reactor step which is used to execute generic actions. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.AshStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/ash_step.ex#L1 "View Source") A reactor step which runs a step-module or an anonymous function, and enqueues any returned notifications before returning. The following return values are supported: `{:ok, result}`, `{:ok, result, notifications}`, `{:ok, result, notifications, new_steps}` Example: ``` ash_step :maybe_update_post do run fn %{post: post, new_amount_of_likes: new_amount_of_likes}, ctx -> opts = Ash.Context.to_opts(ctx, return_notifications?: true) if post.amount_of_likes != new_amount_of_likes do Post.update(post, %{amount_of_likes: new_amount_of_likes}, opts) else {:ok, post} end end ``` ## [](Ash.Reactor.AshStep.html#module-options)Options - `run` - a one or two arity function or MFA which will be called as the run function of the step. - `compensate` - a one to three arity function or MFA which will be called as the compensate function of the step. Optional. - `undo` - a one to three arity function or MFA which will be called as the undo function of this step. Optional. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.BulkCreateStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/bulk_create_step.ex#L1 "View Source") The Reactor stop which is used to execute create actions in bulk. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.BulkUpdateStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/bulk_update_step.ex#L1 "View Source") The Reactor stop which is used to execute create actions in bulk. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.ChangeStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/change_step.ex#L1 "View Source") The Reactor step which is used to execute change steps. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.CreateStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/create_step.ex#L1 "View Source") The Reactor step which is used to execute create actions. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.DestroyStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/destroy_step.ex#L1 "View Source") The Reactor step which is used to execute update actions. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Action (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/action.ex#L1 "View Source") The `action` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Action.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Action.html#types) [t()](Ash.Reactor.Dsl.Action.html#t:t/0) # [](Ash.Reactor.Dsl.Action.html#types)Types [](Ash.Reactor.Dsl.Action.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/action.ex#L25) ``` @type t() :: %Ash.Reactor.Dsl.Action{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), async?: boolean(), authorize?: boolean() | nil, context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), inputs: [Ash.Reactor.Dsl.Inputs.t()], name: atom(), resource: module(), tenant: nil | Ash.Reactor.Dsl.Tenant.t(), transform: term(), type: :action, undo: :always | :never | :outside_transaction, undo_action: atom(), wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.ActionLoad (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/action_load.ex#L1 "View Source") Add a load statement to an action. # [](Ash.Reactor.Dsl.ActionLoad.html#summary)Summary ## [Types](Ash.Reactor.Dsl.ActionLoad.html#types) [t()](Ash.Reactor.Dsl.ActionLoad.html#t:t/0) # [](Ash.Reactor.Dsl.ActionLoad.html#types)Types [](Ash.Reactor.Dsl.ActionLoad.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/action_load.ex#L11) ``` @type t() :: %Ash.Reactor.Dsl.ActionLoad{ __identifier__: any(), source: Reactor.Template.t(), transform: nil | (any() -> any()) | {module(), keyword()} | mfa() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.ActionTransformer (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/action_transformer.ex#L1 "View Source") Responsible for transforming actions. # [](Ash.Reactor.Dsl.ActionTransformer.html#summary)Summary ## [Functions](Ash.Reactor.Dsl.ActionTransformer.html#functions) [after?(\_)](Ash.Reactor.Dsl.ActionTransformer.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Reactor.Dsl.ActionTransformer.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). # [](Ash.Reactor.Dsl.ActionTransformer.html#functions)Functions [](Ash.Reactor.Dsl.ActionTransformer.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/action_transformer.ex#L10) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Reactor.Dsl.ActionTransformer.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/action_transformer.ex#L10) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Actor (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/actor.ex#L1 "View Source") Specify the actor used to execute an action. # [](Ash.Reactor.Dsl.Actor.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Actor.html#types) [t()](Ash.Reactor.Dsl.Actor.html#t:t/0) # [](Ash.Reactor.Dsl.Actor.html#types)Types [](Ash.Reactor.Dsl.Actor.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/actor.ex#L10) ``` @type t() :: %Ash.Reactor.Dsl.Actor{ __identifier__: any(), source: Reactor.Template.t(), transform: nil | (any() -> any()) | {module(), keyword()} | mfa() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.AshStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/ash_step.ex#L1 "View Source") The ash\_step DSL module. See `Reactor.step`. # [](Ash.Reactor.Dsl.AshStep.html#summary)Summary ## [Types](Ash.Reactor.Dsl.AshStep.html#types) [t()](Ash.Reactor.Dsl.AshStep.html#t:t/0) # [](Ash.Reactor.Dsl.AshStep.html#types)Types [](Ash.Reactor.Dsl.AshStep.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/ash_step.ex#L21) ``` @type t() :: %Ash.Reactor.Dsl.AshStep{ __identifier__: any(), arguments: [Reactor.Dsl.Argument.t()], async?: boolean(), compensate: nil | (any(), Reactor.inputs(), Reactor.context() -> :ok | :retry | {:continue, any()}), impl: nil | module() | {module(), keyword()}, max_retries: non_neg_integer() | :infinity, name: atom(), run: nil | (Reactor.inputs(), Reactor.context() -> {:ok, any()} | {:ok, any(), [Reactor.Step.t()]} | {:halt | :error, any()}), transform: nil | (any() -> any()), undo: nil | (any(), Reactor.inputs(), Reactor.context() -> :ok | :retry | {:error, any()}) } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.BulkCreate (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/bulk_create.ex#L1 "View Source") The `bulk_create` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.BulkCreate.html#summary)Summary ## [Types](Ash.Reactor.Dsl.BulkCreate.html#types) [t()](Ash.Reactor.Dsl.BulkCreate.html#t:t/0) # [](Ash.Reactor.Dsl.BulkCreate.html#types)Types [](Ash.Reactor.Dsl.BulkCreate.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/bulk_create.ex#L48) ``` @type t() :: %Ash.Reactor.Dsl.BulkCreate{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), assume_casted?: boolean(), async?: boolean(), authorize?: boolean() | nil, authorize_changeset_with: :filter | :error, authorize_query_with: :filter | :error, batch_size: nil | pos_integer(), context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), initial: Reactor.Template.t(), load: nil | Ash.Reactor.Dsl.ActionLoad.t(), max_concurrency: non_neg_integer(), name: atom(), notification_metadata: map(), notify?: boolean(), read_action: atom(), resource: module(), return_errors?: boolean(), return_records?: boolean(), return_stream?: boolean(), rollback_on_error?: boolean(), select: [atom()], skip_unknown_inputs: [atom() | String.t()], sorted?: boolean(), stop_on_error?: boolean(), success_state: :success | :partial_success, tenant: nil | Ash.Reactor.Dsl.Tenant.t(), timeout: nil | timeout(), transaction: :all | :batch | false, transform: term(), type: :bulk_create, undo: :never, undo_action: nil, upsert?: term(), upsert_fields: [], upsert_identity: nil, wait_for: term() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.BulkUpdate (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/bulk_update.ex#L1 "View Source") The `bulk_update` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.BulkUpdate.html#summary)Summary ## [Types](Ash.Reactor.Dsl.BulkUpdate.html#types) [t()](Ash.Reactor.Dsl.BulkUpdate.html#t:t/0) # [](Ash.Reactor.Dsl.BulkUpdate.html#types)Types [](Ash.Reactor.Dsl.BulkUpdate.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/bulk_update.ex#L56) ``` @type t() :: %Ash.Reactor.Dsl.BulkUpdate{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), allow_stream_with: :keyset | :offset | :full_read, assume_casted?: boolean(), async?: boolean(), atomic_update: %{optional(atom()) => Ash.Expr.t()}, authorize?: boolean() | nil, authorize_changeset_with: :filter | :error, authorize_query?: boolean(), authorize_query_with: :filter | :error, batch_size: nil | pos_integer(), context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), filter: %{ optional(String.t()) => %{ required(String.t()) => String.t() | number() | boolean() } } | Keyword.t(Keyword.t(String.t() | number() | boolean())), initial: Reactor.Template.t(), inputs: [Ash.Reactor.Dsl.Inputs.t()], load: nil | Ash.Reactor.Dsl.ActionLoad.t(), lock: nil | Ash.DataLayer.lock_type(), max_concurrency: non_neg_integer(), name: atom(), notification_metadata: map() | Reactor.Template.t(), notify?: boolean(), page: Keyword.t(), read_action: atom(), resource: module(), return_errors?: boolean(), return_records?: boolean(), return_stream?: boolean(), reuse_values?: boolean(), rollback_on_error?: boolean(), select: [atom()], skip_unknown_inputs: [atom() | String.t()], sorted?: boolean(), stop_on_error?: boolean(), strategy: :atomic | :atomic_batches | :stream, stream_batch_size: nil | pos_integer(), stream_with: nil | :keyset | :offset | :full_read, success_state: :success | :partial_success, tenant: nil | Ash.Reactor.Dsl.Tenant.t(), timeout: nil | timeout(), transaction: :all | :batch | false, transform: term(), type: :bulk_create, undo: :never, undo_action: nil, wait_for: term() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Change (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/change.ex#L1 "View Source") The `change` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Change.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Change.html#types) [t()](Ash.Reactor.Dsl.Change.html#t:t/0) # [](Ash.Reactor.Dsl.Change.html#types)Types [](Ash.Reactor.Dsl.Change.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/change.ex#L19) ``` @type t() :: %Ash.Reactor.Dsl.Change{ __identifier__: any(), action_step?: false, arguments: [Reactor.Dsl.Argument.t()], async?: boolean(), change: Ash.Resource.Change.t() | Ash.Resource.Change.ref(), description: nil | String.t(), fail_if_invalid?: boolean(), initial: nil | Reactor.Template.t(), name: atom(), only_when_valid?: term(), type: :change, where: [Ash.Resource.Validation.ref()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/context.ex#L1 "View Source") Specify context to merge into an action's context. # [](Ash.Reactor.Dsl.Context.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Context.html#types) [t()](Ash.Reactor.Dsl.Context.html#t:t/0) # [](Ash.Reactor.Dsl.Context.html#types)Types [](Ash.Reactor.Dsl.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/context.ex#L10) ``` @type t() :: %Ash.Reactor.Dsl.Context{ __identifier__: any(), context: nil | t() | map(), transform: nil | (any() -> any()) | {module(), keyword()} | mfa() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Create (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/create.ex#L1 "View Source") The `create` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Create.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Create.html#types) [t()](Ash.Reactor.Dsl.Create.html#t:t/0) # [](Ash.Reactor.Dsl.Create.html#types)Types [](Ash.Reactor.Dsl.Create.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/create.ex#L29) ``` @type t() :: %Ash.Reactor.Dsl.Create{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), async?: boolean(), authorize?: boolean() | nil, context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), initial: nil | Ash.Resource.t() | Reactor.Template.t(), inputs: [Ash.Reactor.Dsl.Inputs.t()], load: nil | Ash.Reactor.Dsl.ActionLoad.t(), name: atom(), resource: module(), tenant: nil | Ash.Reactor.Dsl.Tenant.t(), transform: term(), type: :create, undo: :always | :never | :outside_transaction, undo_action: atom(), upsert?: boolean(), upsert_identity: nil | atom(), wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Destroy (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/destroy.ex#L1 "View Source") The `destroy` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Destroy.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Destroy.html#types) [t()](Ash.Reactor.Dsl.Destroy.html#t:t/0) # [](Ash.Reactor.Dsl.Destroy.html#types)Types [](Ash.Reactor.Dsl.Destroy.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/destroy.ex#L28) ``` @type t() :: %Ash.Reactor.Dsl.Destroy{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), async?: boolean(), authorize?: boolean() | nil, context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), initial: Reactor.Template.t(), inputs: [Ash.Reactor.Dsl.Inputs.t()], load: nil | Ash.Reactor.Dsl.ActionLoad.t(), name: atom(), resource: module(), return_destroyed?: boolean(), tenant: nil | Ash.Reactor.Dsl.Tenant.t(), transform: term(), type: :destroy, undo: :always | :never | :outside_transaction, undo_action: atom(), wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Inputs (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/inputs.ex#L1 "View Source") The `inputs` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Inputs.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Inputs.html#types) [t()](Ash.Reactor.Dsl.Inputs.html#t:t/0) # [](Ash.Reactor.Dsl.Inputs.html#types)Types [](Ash.Reactor.Dsl.Inputs.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/inputs.ex#L10) ``` @type t() :: %Ash.Reactor.Dsl.Inputs{ __identifier__: any(), template: %{optional(atom()) => Reactor.Template.t()} | Keyword.t(Reactor.Template.t()), transform: nil | (any() -> any()) | {module(), keyword()} | mfa() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Load (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/load.ex#L1 "View Source") The `load` step entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Load.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Load.html#types) [t()](Ash.Reactor.Dsl.Load.html#t:t/0) # [](Ash.Reactor.Dsl.Load.html#types)Types [](Ash.Reactor.Dsl.Load.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/load.ex#L26) ``` @type t() :: %Ash.Reactor.Dsl.Load{ __identifier__: any(), action: nil | atom(), action_step?: false, actor: nil | Ash.Reactor.Dsl.Actor.t(), async?: boolean(), authorize?: nil | boolean(), context: nil | Ash.Reactor.Dsl.Context.t(), description: nil | String.t(), domain: nil | Ash.Domain.t(), lazy?: nil | boolean(), load: Reactor.Template.t(), name: atom(), records: Reactor.Template.t(), reuse_values?: nil | boolean(), strict?: nil | boolean(), tenant: nil | Ash.Reactor.Dsl.Tenant.t(), transform: nil | (any() -> any()) | {module(), keyword()} | mfa(), type: :load, wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.MiddlewareTransformer (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/middleware_transformer.ex#L1 "View Source") Ensures that the required middlewares are added to the Reactor. # [](Ash.Reactor.Dsl.MiddlewareTransformer.html#summary)Summary ## [Functions](Ash.Reactor.Dsl.MiddlewareTransformer.html#functions) [after?(\_)](Ash.Reactor.Dsl.MiddlewareTransformer.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Reactor.Dsl.MiddlewareTransformer.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). # [](Ash.Reactor.Dsl.MiddlewareTransformer.html#functions)Functions [](Ash.Reactor.Dsl.MiddlewareTransformer.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/middleware_transformer.ex#L8) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Reactor.Dsl.MiddlewareTransformer.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/middleware_transformer.ex#L8) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Read (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/read.ex#L1 "View Source") The `read` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Read.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Read.html#types) [t()](Ash.Reactor.Dsl.Read.html#t:t/0) # [](Ash.Reactor.Dsl.Read.html#types)Types [](Ash.Reactor.Dsl.Read.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/read.ex#L24) ``` @type t() :: %Ash.Reactor.Dsl.Read{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), async?: boolean(), authorize?: boolean() | nil, context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), inputs: [Ash.Reactor.Dsl.Inputs.t()], load: nil | Ash.Reactor.Dsl.ActionLoad.t(), name: atom(), resource: module(), tenant: nil | Ash.Reactor.Dsl.Tenant.t(), transform: term(), type: :create, wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.ReadOne (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/read_one.ex#L1 "View Source") The `read_one` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.ReadOne.html#summary)Summary ## [Types](Ash.Reactor.Dsl.ReadOne.html#types) [t()](Ash.Reactor.Dsl.ReadOne.html#t:t/0) # [](Ash.Reactor.Dsl.ReadOne.html#types)Types [](Ash.Reactor.Dsl.ReadOne.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/read_one.ex#L25) ``` @type t() :: %Ash.Reactor.Dsl.ReadOne{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), async?: boolean(), authorize?: boolean() | nil, context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), fail_on_not_found?: boolean(), inputs: [Ash.Reactor.Dsl.Inputs.t()], load: nil | Ash.Reactor.Dsl.ActionLoad.t(), name: atom(), resource: module(), tenant: nil | Ash.Reactor.Dsl.Tenant.t(), transform: term(), type: :create, wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Tenant (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/tenant.ex#L1 "View Source") Specify the tenant used to execute an action. # [](Ash.Reactor.Dsl.Tenant.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Tenant.html#types) [t()](Ash.Reactor.Dsl.Tenant.html#t:t/0) # [](Ash.Reactor.Dsl.Tenant.html#types)Types [](Ash.Reactor.Dsl.Tenant.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/tenant.ex#L10) ``` @type t() :: %Ash.Reactor.Dsl.Tenant{ __identifier__: any(), source: Reactor.Template.t(), transform: nil | (any() -> any()) | {module(), keyword()} | mfa() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Transaction (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/transaction.ex#L1 "View Source") The `transaction` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Transaction.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Transaction.html#types) [t()](Ash.Reactor.Dsl.Transaction.html#t:t/0) # [](Ash.Reactor.Dsl.Transaction.html#types)Types [](Ash.Reactor.Dsl.Transaction.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/transaction.ex#L21) ``` @type t() :: %Ash.Reactor.Dsl.Transaction{ __identifier__: any(), arguments: [], description: nil | String.t(), name: atom(), resources: [Ash.Resource.t()], return: atom(), steps: [Reactor.Step.t()], timeout: timeout(), type: :transaction, wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Dsl.Update (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/update.ex#L1 "View Source") The `update` entity for the [`Ash.Reactor`](Ash.Reactor.html) reactor extension. # [](Ash.Reactor.Dsl.Update.html#summary)Summary ## [Types](Ash.Reactor.Dsl.Update.html#types) [t()](Ash.Reactor.Dsl.Update.html#t:t/0) # [](Ash.Reactor.Dsl.Update.html#types)Types [](Ash.Reactor.Dsl.Update.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/dsl/update.ex#L27) ``` @type t() :: %Ash.Reactor.Dsl.Update{ __identifier__: any(), action: atom(), action_step?: true, actor: nil | Ash.Reactor.Dsl.Actor.t(), async?: boolean(), authorize?: boolean() | nil, context: nil | Ash.Reactor.Dsl.Context.t(), description: String.t() | nil, domain: Ash.Domain.t(), initial: Reactor.Template.t(), inputs: [Ash.Reactor.Dsl.Inputs.t()], load: nil | Ash.Reactor.Dsl.ActionLoad.t(), name: atom(), resource: module(), tenant: nil | Ash.Reactor.Dsl.Tenant.t(), transform: term(), type: :update, undo: :always | :never | :outside_transaction, undo_action: atom(), wait_for: [Reactor.Dsl.WaitFor.t()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/reactor.ex#L1 "View Source") [`Ash.Reactor`](Ash.Reactor.html) is a [`Reactor`](https://hex.pm/packages/reactor) extension which provides steps for working with Ash resources and actions. See the [Ash Reactor Guide](reactor.html) for more information. # [](Ash.Reactor.html#summary)Summary ## [Types](Ash.Reactor.html#types) [action()](Ash.Reactor.html#t:action/0) ## [Functions](Ash.Reactor.html#functions) [ash(body)](Ash.Reactor.html#ash/1) # [](Ash.Reactor.html#types)Types [](Ash.Reactor.html#t:action/0) # action() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/reactor.ex#L21) ``` @type action() :: Ash.Reactor.Dsl.Action.t() | Ash.Reactor.Dsl.AshStep.t() | Ash.Reactor.Dsl.BulkCreate.t() | Ash.Reactor.Dsl.BulkUpdate.t() | Ash.Reactor.Dsl.Create.t() | Ash.Reactor.Dsl.Destroy.t() | Ash.Reactor.Dsl.Load.t() | Ash.Reactor.Dsl.Read.t() | Ash.Reactor.Dsl.ReadOne.t() | Ash.Reactor.Dsl.Update.t() ``` # [](Ash.Reactor.html#functions)Functions [](Ash.Reactor.html#ash/1) # ash(body) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/reactor.ex#L33) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.LoadStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/load_step.ex#L1 "View Source") The Reactor step which is used to execute load steps. # [](Ash.Reactor.LoadStep.html#summary)Summary ## [Functions](Ash.Reactor.LoadStep.html#functions) [run(arguments, context, options)](Ash.Reactor.LoadStep.html#run/3) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). # [](Ash.Reactor.LoadStep.html#functions)Functions [](Ash.Reactor.LoadStep.html#run/3) # run(arguments, context, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/load_step.ex#L8) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.MergeInputsStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/merge_inputs_step.ex#L1 "View Source") A custom step which merges any number of `inputs` results into a single map. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Notifications (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/notifications.ex#L1 "View Source") Reactor middleware used to collect and emit notifications upon successful completion of the Reactor. # [](Ash.Reactor.Notifications.html#summary)Summary ## [Functions](Ash.Reactor.Notifications.html#functions) [complete(result, context)](Ash.Reactor.Notifications.html#complete/2) When the reactor completes successfully, publish any queued notifications. [enqueue\_notifications(context, notifications)](Ash.Reactor.Notifications.html#enqueue_notifications/2) Add notifications to the queue to be published on reactor success. [error(errors, context)](Ash.Reactor.Notifications.html#error/2) When the reactor fails, discard any queued notifications. [halt(context)](Ash.Reactor.Notifications.html#halt/1) When halting the reactor, store any queued notifications in the context for eventual resumption. [init(context)](Ash.Reactor.Notifications.html#init/1) When starting a reactor, start an agent to act as a temporary store of notifications. [publish(context, notifications)](Ash.Reactor.Notifications.html#publish/2) Dispatch notifications. # [](Ash.Reactor.Notifications.html#functions)Functions [](Ash.Reactor.Notifications.html#complete/2) # complete(result, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/notifications.ex#L67) When the reactor completes successfully, publish any queued notifications. [](Ash.Reactor.Notifications.html#enqueue_notifications/2) # enqueue\_notifications(context, notifications) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/notifications.ex#L109) ``` @spec enqueue_notifications( Reactor.context(), Enumerable.t(Ash.Notifier.Notification.t()) ) :: :ok | {:error, any()} ``` Add notifications to the queue to be published on reactor success. [](Ash.Reactor.Notifications.html#error/2) # error(errors, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/notifications.ex#L98) When the reactor fails, discard any queued notifications. [](Ash.Reactor.Notifications.html#halt/1) # halt(context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/notifications.ex#L46) When halting the reactor, store any queued notifications in the context for eventual resumption. [](Ash.Reactor.Notifications.html#init/1) # init(context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/notifications.ex#L27) When starting a reactor, start an agent to act as a temporary store of notifications. [](Ash.Reactor.Notifications.html#publish/2) # publish(context, notifications) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/notifications.ex#L123) ``` @spec publish( Reactor.context(), Ash.Notifier.Notification.t() | [Ash.Notifier.Notification.t()] ) :: [Ash.Notifier.Notification.t()] ``` Dispatch notifications. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.ReadOneStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/read_one_step.ex#L1 "View Source") The Reactor step which is used to execute get actions. # [](Ash.Reactor.ReadOneStep.html#summary)Summary ## [Functions](Ash.Reactor.ReadOneStep.html#functions) [run(arguments, context, options)](Ash.Reactor.ReadOneStep.html#run/3) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). # [](Ash.Reactor.ReadOneStep.html#functions)Functions [](Ash.Reactor.ReadOneStep.html#run/3) # run(arguments, context, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/read_one_step.ex#L10) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.ReadStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/read_step.ex#L1 "View Source") The Reactor step which is used to execute read actions. # [](Ash.Reactor.ReadStep.html#summary)Summary ## [Functions](Ash.Reactor.ReadStep.html#functions) [run(arguments, context, options)](Ash.Reactor.ReadStep.html#run/3) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). # [](Ash.Reactor.ReadStep.html#functions)Functions [](Ash.Reactor.ReadStep.html#run/3) # run(arguments, context, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/read_step.ex#L10) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.Tracer (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/tracer.ex#L1 "View Source") Reactor middleware which threads Ash's tracing information through to new processes spawned by Reactor. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.TransactionStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/transaction_step.ex#L1 "View Source") The Reactor step which is used to wrap other steps in an Ash data layer transaction. # [](Ash.Reactor.TransactionStep.html#summary)Summary ## [Functions](Ash.Reactor.TransactionStep.html#functions) [run(arguments, context, options)](Ash.Reactor.TransactionStep.html#run/3) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). # [](Ash.Reactor.TransactionStep.html#functions)Functions [](Ash.Reactor.TransactionStep.html#run/3) # run(arguments, context, options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/transaction_step.ex#L8) Callback implementation for [`Reactor.Step.run/3`](../reactor/0.10.3/Reactor.Step.html#c:run/3). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor.UpdateStep (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/reactor/steps/update_step.ex#L1 "View Source") The Reactor step which is used to execute update actions. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Action (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/action/action.ex#L1 "View Source") Represents a custom action on a resource. # [](Ash.Resource.Actions.Action.html#summary)Summary ## [Types](Ash.Resource.Actions.Action.html#types) [t()](Ash.Resource.Actions.Action.html#t:t/0) ## [Functions](Ash.Resource.Actions.Action.html#functions) [transform(action)](Ash.Resource.Actions.Action.html#transform/1) # [](Ash.Resource.Actions.Action.html#types)Types [](Ash.Resource.Actions.Action.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/action/action.ex#L19) ``` @type t() :: %Ash.Resource.Actions.Action{ allow_nil?: boolean(), arguments: [Ash.Resource.Actions.Argument.t()], constraints: Keyword.t(), description: String.t() | nil, name: atom(), primary?: boolean(), returns: Ash.Type.t() | nil, run: {module(), Keyword.t()}, skip_unknown_inputs: [atom() | String.t()], touches_resources: [Ash.Resource.t()], transaction?: boolean(), type: :action } ``` # [](Ash.Resource.Actions.Action.html#functions)Functions [](Ash.Resource.Actions.Action.html#transform/1) # transform(action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/action/action.ex#L36) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Argument (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/argument.ex#L1 "View Source") Represents an argument to an action # [](Ash.Resource.Actions.Argument.html#summary)Summary ## [Types](Ash.Resource.Actions.Argument.html#types) [t()](Ash.Resource.Actions.Argument.html#t:t/0) ## [Functions](Ash.Resource.Actions.Argument.html#functions) [schema()](Ash.Resource.Actions.Argument.html#schema/0) # [](Ash.Resource.Actions.Argument.html#types)Types [](Ash.Resource.Actions.Argument.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/argument.ex#L14) ``` @type t() :: %Ash.Resource.Actions.Argument{ allow_nil?: term(), constraints: term(), default: term(), description: term(), name: term(), public?: term(), sensitive?: term(), type: term() } ``` # [](Ash.Resource.Actions.Argument.html#functions)Functions [](Ash.Resource.Actions.Argument.html#schema/0) # schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/argument.ex#L16) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Create (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/create.ex#L1 "View Source") Represents a create action on a resource. # [](Ash.Resource.Actions.Create.html#summary)Summary ## [Types](Ash.Resource.Actions.Create.html#types) [t()](Ash.Resource.Actions.Create.html#t:t/0) # [](Ash.Resource.Actions.Create.html#types)Types [](Ash.Resource.Actions.Create.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/create.ex#L31) ``` @type t() :: %Ash.Resource.Actions.Create{ accept: nil | [atom()], action_select: [atom()] | nil, allow_nil_input: [atom()], arguments: [Ash.Resource.Actions.Argument.t()], changes: term(), delay_global_validations?: boolean(), description: String.t() | nil, error_handler: term(), manual: module() | nil, metadata: term(), name: atom(), notifiers: [module()], primary?: boolean(), reject: term(), require_attributes: [atom()], return_skipped_upsert?: boolean(), skip_global_validations?: boolean(), skip_unknown_inputs: [atom() | String.t()], touches_resources: [atom()], transaction?: term(), type: :create, upsert?: boolean(), upsert_condition: Ash.Expr.t() | nil, upsert_fields: nil | [atom()] | :replace_all | {:replace, [atom()]} | {:replace_all_except, [atom()]}, upsert_identity: atom() | nil } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Destroy (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/destroy.ex#L1 "View Source") Represents a destroy action on a resource. # [](Ash.Resource.Actions.Destroy.html#summary)Summary ## [Types](Ash.Resource.Actions.Destroy.html#types) [t()](Ash.Resource.Actions.Destroy.html#t:t/0) ## [Functions](Ash.Resource.Actions.Destroy.html#functions) [transform(action)](Ash.Resource.Actions.Destroy.html#transform/1) # [](Ash.Resource.Actions.Destroy.html#types)Types [](Ash.Resource.Actions.Destroy.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/destroy.ex#L33) ``` @type t() :: %Ash.Resource.Actions.Destroy{ accept: nil | [atom()], action_select: [atom()] | nil, allow_nil_input: [atom()], arguments: [Ash.Resource.Actions.Argument.t()], atomic_upgrade?: boolean(), atomic_upgrade_with: atom() | nil, changes: term(), delay_global_validations?: boolean(), description: String.t() | nil, error_handler: term(), manual: module() | nil, metadata: term(), name: atom(), notifiers: [module()], primary?: boolean(), reject: term(), require_atomic?: boolean(), require_attributes: [atom()], skip_global_validations?: boolean(), skip_unknown_inputs: [atom() | String.t()], soft?: term(), touches_resources: [atom()], transaction?: term(), type: :destroy } ``` # [](Ash.Resource.Actions.Destroy.html#functions)Functions [](Ash.Resource.Actions.Destroy.html#transform/1) # transform(action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/destroy.ex#L105) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/actions.ex#L1 "View Source") Types for Ash actions # [](Ash.Resource.Actions.html#summary)Summary ## [Types](Ash.Resource.Actions.html#types) [action()](Ash.Resource.Actions.html#t:action/0) [action\_type()](Ash.Resource.Actions.html#t:action_type/0) # [](Ash.Resource.Actions.html#types)Types [](Ash.Resource.Actions.html#t:action/0) # action() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/actions.ex#L5) ``` @type action() :: Ash.Resource.Actions.Action.t() | Ash.Resource.Actions.Create.t() | Ash.Resource.Actions.Read.t() | Ash.Resource.Actions.Update.t() | Ash.Resource.Actions.Destroy.t() ``` [](Ash.Resource.Actions.html#t:action_type/0) # action\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/actions.ex#L6) ``` @type action_type() :: :action | :read | :create | :update | :destroy ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Implementation.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/action/implementation.ex#L6 "View Source") The context passed into generic action functions # [](Ash.Resource.Actions.Implementation.Context.html#summary)Summary ## [Types](Ash.Resource.Actions.Implementation.Context.html#types) [t()](Ash.Resource.Actions.Implementation.Context.html#t:t/0) # [](Ash.Resource.Actions.Implementation.Context.html#types)Types [](Ash.Resource.Actions.Implementation.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/action/implementation.ex#L11) ``` @type t() :: %Ash.Resource.Actions.Implementation.Context{ actor: term(), authorize?: boolean(), domain: module(), tenant: term() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Implementation behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/action/implementation.ex#L1 "View Source") An implementation of a generic action. # [](Ash.Resource.Actions.Implementation.html#summary)Summary ## [Callbacks](Ash.Resource.Actions.Implementation.html#callbacks) [run(t, opts, t)](Ash.Resource.Actions.Implementation.html#c:run/3) # [](Ash.Resource.Actions.Implementation.html#callbacks)Callbacks [](Ash.Resource.Actions.Implementation.html#c:run/3) # run(t, opts, t) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/action/implementation.ex#L19) ``` @callback run( Ash.ActionInput.t(), opts :: Keyword.t(), Ash.Resource.Actions.Implementation.Context.t() ) :: :ok | {:ok, term()} | {:ok, [Ash.Notifier.Notification.t()]} | {:error, term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Metadata (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/metadata.ex#L1 "View Source") Represents metadata from an action # [](Ash.Resource.Actions.Metadata.html#summary)Summary ## [Types](Ash.Resource.Actions.Metadata.html#types) [t()](Ash.Resource.Actions.Metadata.html#t:t/0) ## [Functions](Ash.Resource.Actions.Metadata.html#functions) [schema()](Ash.Resource.Actions.Metadata.html#schema/0) # [](Ash.Resource.Actions.Metadata.html#types)Types [](Ash.Resource.Actions.Metadata.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/metadata.ex#L12) ``` @type t() :: %Ash.Resource.Actions.Metadata{ allow_nil?: term(), constraints: term(), default: term(), description: term(), name: term(), type: term() } ``` # [](Ash.Resource.Actions.Metadata.html#functions)Functions [](Ash.Resource.Actions.Metadata.html#schema/0) # schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/metadata.ex#L14) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Read (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/read.ex#L1 "View Source") Represents a read action on a resource. # [](Ash.Resource.Actions.Read.html#summary)Summary ## [Types](Ash.Resource.Actions.Read.html#types) [t()](Ash.Resource.Actions.Read.html#t:t/0) ## [Functions](Ash.Resource.Actions.Read.html#functions) [pagination\_schema()](Ash.Resource.Actions.Read.html#pagination_schema/0) [transform(read)](Ash.Resource.Actions.Read.html#transform/1) # [](Ash.Resource.Actions.Read.html#types)Types [](Ash.Resource.Actions.Read.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/read.ex#L24) ``` @type t() :: %Ash.Resource.Actions.Read{ arguments: [Ash.Resource.Actions.Argument.t()], description: String.t() | nil, filter: any(), filters: [any()], get?: nil | boolean(), get_by: nil | atom() | [atom()], manual: atom() | {atom(), Keyword.t()} | nil, metadata: [Ash.Resource.Actions.Metadata.t()], modify_query: nil | mfa(), multitenancy: atom(), name: atom(), pagination: any(), preparations: term(), primary?: boolean(), skip_unknown_inputs: [atom() | String.t()], timeout: pos_integer() | nil, touches_resources: [atom()], transaction?: boolean(), type: :read } ``` # [](Ash.Resource.Actions.Read.html#functions)Functions [](Ash.Resource.Actions.Read.html#pagination_schema/0) # pagination\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/read.ex#L193) [](Ash.Resource.Actions.Read.html#transform/1) # transform(read) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/read.ex#L154) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Read.Pagination (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/read.ex#L132 "View Source") Represents the pagination configuration of a read action # [](Ash.Resource.Actions.Read.Pagination.html#summary)Summary ## [Types](Ash.Resource.Actions.Read.Pagination.html#types) [t()](Ash.Resource.Actions.Read.Pagination.html#t:t/0) ## [Functions](Ash.Resource.Actions.Read.Pagination.html#functions) [transform(pagination)](Ash.Resource.Actions.Read.Pagination.html#transform/1) # [](Ash.Resource.Actions.Read.Pagination.html#types)Types [](Ash.Resource.Actions.Read.Pagination.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/read.ex#L143) ``` @type t() :: %Ash.Resource.Actions.Read.Pagination{ countable: term(), default_limit: term(), keyset?: term(), max_page_size: term(), offset?: term(), required?: term() } ``` # [](Ash.Resource.Actions.Read.Pagination.html#functions)Functions [](Ash.Resource.Actions.Read.Pagination.html#transform/1) # transform(pagination) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/read.ex#L145) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Actions.Update (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/update.ex#L1 "View Source") Represents a update action on a resource. # [](Ash.Resource.Actions.Update.html#summary)Summary ## [Types](Ash.Resource.Actions.Update.html#types) [t()](Ash.Resource.Actions.Update.html#t:t/0) ## [Functions](Ash.Resource.Actions.Update.html#functions) [transform(action)](Ash.Resource.Actions.Update.html#transform/1) # [](Ash.Resource.Actions.Update.html#types)Types [](Ash.Resource.Actions.Update.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/update.ex#L34) ``` @type t() :: %Ash.Resource.Actions.Update{ accept: nil | [atom()], action_select: [atom()] | nil, allow_nil_input: [atom()], arguments: [Ash.Resource.Actions.Argument.t()], atomic_upgrade?: boolean(), atomic_upgrade_with: atom() | nil, atomics: term(), changes: term(), delay_global_validations?: boolean(), description: String.t() | nil, error_handler: term(), manual: module() | nil, manual?: term(), metadata: term(), name: atom(), notifiers: [module()], primary?: boolean(), reject: term(), require_atomic?: boolean(), require_attributes: [atom()], skip_global_validations?: boolean(), skip_unknown_inputs: [atom() | String.t()], touches_resources: [atom()], transaction?: term(), type: :update } ``` # [](Ash.Resource.Actions.Update.html#functions)Functions [](Ash.Resource.Actions.Update.html#transform/1) # transform(action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/actions/update.ex#L102) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Aggregate.CustomAggregate behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/aggregate/custom_aggregate.ex#L1 "View Source") The root behavior for a custom aggregate. See data layers for their implementation of custom aggregates. # [](Ash.Resource.Aggregate.CustomAggregate.html#summary)Summary ## [Types](Ash.Resource.Aggregate.CustomAggregate.html#types) [t()](Ash.Resource.Aggregate.CustomAggregate.html#t:t/0) ## [Callbacks](Ash.Resource.Aggregate.CustomAggregate.html#callbacks) [describe(t)](Ash.Resource.Aggregate.CustomAggregate.html#c:describe/1) # [](Ash.Resource.Aggregate.CustomAggregate.html#types)Types [](Ash.Resource.Aggregate.CustomAggregate.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/aggregate/custom_aggregate.ex#L7) ``` @type t() :: {module(), Keyword.t()} ``` # [](Ash.Resource.Aggregate.CustomAggregate.html#callbacks)Callbacks [](Ash.Resource.Aggregate.CustomAggregate.html#c:describe/1) # describe(t) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/aggregate/custom_aggregate.ex#L8) ``` @callback describe(t()) :: String.t() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Aggregate (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/aggregate/aggregate.ex#L1 "View Source") Represents a named aggregate on the resource that can be loaded # [](Ash.Resource.Aggregate.html#summary)Summary ## [Types](Ash.Resource.Aggregate.html#types) [t()](Ash.Resource.Aggregate.html#t:t/0) # [](Ash.Resource.Aggregate.html#types)Types [](Ash.Resource.Aggregate.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/aggregate/aggregate.ex#L110) ``` @type t() :: %Ash.Resource.Aggregate{ authorize?: boolean(), constraints: term(), default: term(), description: String.t() | nil, field: atom(), filter: Keyword.t(), filterable?: boolean(), implementation: term(), include_nil?: term(), join_filters: %{required([atom()]) => term()}, kind: Ash.Query.Aggregate.kind(), name: atom(), public?: boolean(), read_action: atom() | nil, relationship_path: [atom()], sensitive?: boolean(), sort: term(), sortable?: boolean(), type: term(), uniq?: term() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Aggregate.JoinFilter (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/aggregate/aggregate.ex#L26 "View Source") Represents a join filter on a resource aggregate [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Attribute.Helpers (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L25 "View Source") Helpers for building attributes # [](Ash.Resource.Attribute.Helpers.html#summary)Summary ## [Functions](Ash.Resource.Attribute.Helpers.html#functions) [timestamps(opts \\\\ \[\])](Ash.Resource.Attribute.Helpers.html#timestamps/1) Defines create and update timestamp attributes. # [](Ash.Resource.Attribute.Helpers.html#functions)Functions [](Ash.Resource.Attribute.Helpers.html#timestamps/1) # timestamps(opts \\\\ \[]) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L36) Defines create and update timestamp attributes. Shorthand for `Ash.Resource.Dsl.attributes.create_timestamp` and `Ash.Resource.Dsl.attributes.update_timestamp` with the attribute names `:inserted_at` and `:updated_at` respectively. Any options passed to this helper are passed to both timestamp macros. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Attribute (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L1 "View Source") Represents an attribute on a resource # [](Ash.Resource.Attribute.html#summary)Summary ## [Types](Ash.Resource.Attribute.html#types) [t()](Ash.Resource.Attribute.html#t:t/0) ## [Functions](Ash.Resource.Attribute.html#functions) [create\_timestamp\_schema()](Ash.Resource.Attribute.html#create_timestamp_schema/0) [integer\_primary\_key\_schema()](Ash.Resource.Attribute.html#integer_primary_key_schema/0) [transform(attribute)](Ash.Resource.Attribute.html#transform/1) [update\_timestamp\_schema()](Ash.Resource.Attribute.html#update_timestamp_schema/0) [uuid\_primary\_key\_schema()](Ash.Resource.Attribute.html#uuid_primary_key_schema/0) [uuid\_v7\_primary\_key\_schema()](Ash.Resource.Attribute.html#uuid_v7_primary_key_schema/0) # [](Ash.Resource.Attribute.html#types)Types [](Ash.Resource.Attribute.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L44) ``` @type t() :: %Ash.Resource.Attribute{ allow_nil?: term(), always_select?: term(), constraints: Keyword.t(), default: nil | term() | (-> term()), description: term(), filterable?: term(), generated?: term(), match_other_defaults?: term(), name: atom(), primary_key?: boolean(), public?: boolean(), select_by_default?: boolean(), sensitive?: boolean(), sortable?: boolean(), source: term(), type: Ash.Type.t(), update_default: nil | term() | (-> term()) | (Ash.Resource.record() -> term()), writable?: boolean() } ``` # [](Ash.Resource.Attribute.html#functions)Functions [](Ash.Resource.Attribute.html#create_timestamp_schema/0) # create\_timestamp\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L230) [](Ash.Resource.Attribute.html#integer_primary_key_schema/0) # integer\_primary\_key\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L234) [](Ash.Resource.Attribute.html#transform/1) # transform(attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L224) [](Ash.Resource.Attribute.html#update_timestamp_schema/0) # update\_timestamp\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L231) [](Ash.Resource.Attribute.html#uuid_primary_key_schema/0) # uuid\_primary\_key\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L232) [](Ash.Resource.Attribute.html#uuid_v7_primary_key_schema/0) # uuid\_v7\_primary\_key\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/attribute.ex#L233) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Builder (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L1 "View Source") Tools for transforming resources in DSL Transformers. # [](Ash.Resource.Builder.html#summary)Summary ## [Functions](Ash.Resource.Builder.html#functions) [add\_action(dsl\_state, type, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_action/4) Builds and adds an action [add\_aggregate(dsl\_state, name, kind, relationship\_path, opts \\\\ \[\])](Ash.Resource.Builder.html#add_aggregate/5) Builds and adds an aggregate to a resource [add\_attribute(dsl\_state, name, type, opts \\\\ \[\])](Ash.Resource.Builder.html#add_attribute/4) Builds and adds an attribute to a resource [add\_calculation(dsl\_state, name, type, calculation, opts \\\\ \[\])](Ash.Resource.Builder.html#add_calculation/5) Builds and adds a calculation to a resource [add\_calculation\_interface(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_calculation_interface/3) Builds and adds an calculation interface to a resource [add\_change(dsl\_state, ref, opts \\\\ \[\])](Ash.Resource.Builder.html#add_change/3) Builds and adds a change [add\_create\_timestamp(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_create_timestamp/3) Builds and adds a create\_timestamp to a resource [add\_identity(dsl\_state, name, fields, opts \\\\ \[\])](Ash.Resource.Builder.html#add_identity/4) Builds and adds an identity [add\_interface(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_interface/3) Builds and adds an interface to a resource [add\_new\_action(dsl\_state, type, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_action/4) Builds and adds a new action unless an action with that name already exists [add\_new\_aggregate(dsl\_state, name, kind, relationship\_path, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_aggregate/5) Builds and adds an aggregate unless an aggregate with that name already exists [add\_new\_attribute(dsl\_state, name, type, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_attribute/4) Builds and adds an attribute unless an attribute with that name already exists [add\_new\_calculation(dsl\_state, name, type, calculation, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_calculation/5) Builds and adds a calculation unless a calculation with that name already exists [add\_new\_calculation\_interface(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_calculation_interface/3) Builds and adds an calculation interface unless an calculation interface with that name already exists [add\_new\_create\_timestamp(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_create_timestamp/3) Builds and adds a create\_timestamp unless a create\_timestamp with that name already exists [add\_new\_identity(dsl\_state, name, fields, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_identity/4) Builds and adds a new identity unless an identity with that name already exists [add\_new\_interface(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_interface/3) Builds and adds an interface unless an interface with that name already exists [add\_new\_relationship(dsl\_state, type, name, destination, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_relationship/5) Builds and adds a new relationship unless a relationship with that name already exists [add\_new\_update\_timestamp(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_new_update_timestamp/3) Builds and adds an update\_timestamp unless an update\_timestamp with that name already exists [add\_preparation(dsl\_state, ref, opts \\\\ \[\])](Ash.Resource.Builder.html#add_preparation/3) Builds and adds a preparation [add\_relationship(dsl\_state, type, name, destination, opts \\\\ \[\])](Ash.Resource.Builder.html#add_relationship/5) Builds and adds an action [add\_update\_timestamp(dsl\_state, name, opts \\\\ \[\])](Ash.Resource.Builder.html#add_update_timestamp/3) Builds and adds an update\_timestamp [build\_action(type, name, opts \\\\ \[\])](Ash.Resource.Builder.html#build_action/3) Builds an action [build\_action\_argument(name, type, opts \\\\ \[\])](Ash.Resource.Builder.html#build_action_argument/3) Builds an action argument [build\_action\_change(change, opts \\\\ \[\])](Ash.Resource.Builder.html#build_action_change/2) Builds an action change [build\_action\_metadata(name, type, opts \\\\ \[\])](Ash.Resource.Builder.html#build_action_metadata/3) Builds an action metadata [build\_action\_validation(validation, opts \\\\ \[\])](Ash.Resource.Builder.html#build_action_validation/2) Builds an action validation [build\_aggregate(name, kind, relationship\_path, opts \\\\ \[\])](Ash.Resource.Builder.html#build_aggregate/4) Builds a calculation with the given name, type, and options [build\_attribute(name, type, opts \\\\ \[\])](Ash.Resource.Builder.html#build_attribute/3) Builds an attribute with the given name, type, and options [build\_calculation(name, type, calculation, opts \\\\ \[\])](Ash.Resource.Builder.html#build_calculation/4) Builds a calculation with the given name, type, and options [build\_calculation\_argument(name, type, opts \\\\ \[\])](Ash.Resource.Builder.html#build_calculation_argument/3) Builds a calculation argument [build\_calculation\_interface(name, opts \\\\ \[\])](Ash.Resource.Builder.html#build_calculation_interface/2) Builds an calculation interface with the given name, type, and options [build\_change(ref, opts \\\\ \[\])](Ash.Resource.Builder.html#build_change/2) Builds a change [build\_create\_timestamp(name, opts \\\\ \[\])](Ash.Resource.Builder.html#build_create_timestamp/2) Builds an create\_timestamp with the given name, type, and options [build\_identity(name, fields, opts \\\\ \[\])](Ash.Resource.Builder.html#build_identity/3) Builds an action [build\_interface(name, opts \\\\ \[\])](Ash.Resource.Builder.html#build_interface/2) Builds an interface with the given name, type, and options [build\_pagination(opts \\\\ \[\])](Ash.Resource.Builder.html#build_pagination/1) Builds a pagination object [build\_preparation(ref, opts \\\\ \[\])](Ash.Resource.Builder.html#build_preparation/2) Builds a preparation [build\_relationship(type, name, destination, opts \\\\ \[\])](Ash.Resource.Builder.html#build_relationship/4) Builds a relationship [build\_update\_timestamp(name, opts \\\\ \[\])](Ash.Resource.Builder.html#build_update_timestamp/2) Builds an update\_timestamp with the given name, type, and options [prepend\_action(dsl\_state, type, name, opts \\\\ \[\])](Ash.Resource.Builder.html#prepend_action/4) Builds and adds an action to the front of the actions list # [](Ash.Resource.Builder.html#functions)Functions [](Ash.Resource.Builder.html#add_action/4) # add\_action(dsl\_state, type, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L37) ``` @spec add_action( Spark.Dsl.Builder.input(), type :: Ash.Resource.Actions.action_type(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an action [](Ash.Resource.Builder.html#add_aggregate/5) # add\_aggregate(dsl\_state, name, kind, relationship\_path, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L591) ``` @spec add_aggregate( Spark.Dsl.Builder.input(), name :: atom(), kind :: Ash.Query.Aggregate.kind(), relationship_path :: atom() | [atom()], opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an aggregate to a resource [](Ash.Resource.Builder.html#add_attribute/4) # add\_attribute(dsl\_state, name, type, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L483) ``` @spec add_attribute( Spark.Dsl.Builder.input(), name :: atom(), type :: Ash.Type.t(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an attribute to a resource [](Ash.Resource.Builder.html#add_calculation/5) # add\_calculation(dsl\_state, name, type, calculation, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L533) ``` @spec add_calculation( Spark.Dsl.Builder.input(), name :: atom(), type :: Ash.Type.t(), calculation :: module() | {module(), Keyword.t()}, opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a calculation to a resource [](Ash.Resource.Builder.html#add_calculation_interface/3) # add\_calculation\_interface(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L688) ``` @spec add_calculation_interface( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an calculation interface to a resource [](Ash.Resource.Builder.html#add_change/3) # add\_change(dsl\_state, ref, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L210) ``` @spec add_change( Spark.Dsl.Builder.input(), ref :: module() | {module(), Keyword.t()}, opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a change [](Ash.Resource.Builder.html#add_create_timestamp/3) # add\_create\_timestamp(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L435) ``` @spec add_create_timestamp( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a create\_timestamp to a resource [](Ash.Resource.Builder.html#add_identity/4) # add\_identity(dsl\_state, name, fields, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L177) ``` @spec add_identity( Spark.Dsl.Builder.input(), name :: atom(), fields :: atom() | [atom()], opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an identity [](Ash.Resource.Builder.html#add_interface/3) # add\_interface(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L642) ``` @spec add_interface( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an interface to a resource [](Ash.Resource.Builder.html#add_new_action/4) # add\_new\_action(dsl\_state, type, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L19) ``` @spec add_new_action( Spark.Dsl.Builder.input(), type :: Ash.Resource.Actions.action_type(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a new action unless an action with that name already exists [](Ash.Resource.Builder.html#add_new_aggregate/5) # add\_new\_aggregate(dsl\_state, name, kind, relationship\_path, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L572) ``` @spec add_new_aggregate( Spark.Dsl.Builder.input(), name :: atom(), kind :: Ash.Query.Aggregate.kind(), relationship_path :: atom() | [atom()], opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an aggregate unless an aggregate with that name already exists [](Ash.Resource.Builder.html#add_new_attribute/4) # add\_new\_attribute(dsl\_state, name, type, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L465) ``` @spec add_new_attribute( Spark.Dsl.Builder.input(), name :: atom(), type :: Ash.Type.t(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an attribute unless an attribute with that name already exists [](Ash.Resource.Builder.html#add_new_calculation/5) # add\_new\_calculation(dsl\_state, name, type, calculation, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L514) ``` @spec add_new_calculation( Spark.Dsl.Builder.input(), name :: atom(), type :: Ash.Type.t(), calculation :: module() | {module(), Keyword.t()} | Ash.Expr.t(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a calculation unless a calculation with that name already exists [](Ash.Resource.Builder.html#add_new_calculation_interface/3) # add\_new\_calculation\_interface(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L671) ``` @spec add_new_calculation_interface( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an calculation interface unless an calculation interface with that name already exists [](Ash.Resource.Builder.html#add_new_create_timestamp/3) # add\_new\_create\_timestamp(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L418) ``` @spec add_new_create_timestamp( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a create\_timestamp unless a create\_timestamp with that name already exists [](Ash.Resource.Builder.html#add_new_identity/4) # add\_new\_identity(dsl\_state, name, fields, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L159) ``` @spec add_new_identity( Spark.Dsl.Builder.input(), name :: atom(), fields :: atom() | [atom()], opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a new identity unless an identity with that name already exists [](Ash.Resource.Builder.html#add_new_interface/3) # add\_new\_interface(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L625) ``` @spec add_new_interface( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an interface unless an interface with that name already exists [](Ash.Resource.Builder.html#add_new_relationship/5) # add\_new\_relationship(dsl\_state, type, name, destination, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L105) ``` @spec add_new_relationship( Spark.Dsl.Builder.input(), type :: Ash.Resource.Relationships.type(), name :: atom(), destination :: module(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a new relationship unless a relationship with that name already exists [](Ash.Resource.Builder.html#add_new_update_timestamp/3) # add\_new\_update\_timestamp(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L380) ``` @spec add_new_update_timestamp( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an update\_timestamp unless an update\_timestamp with that name already exists [](Ash.Resource.Builder.html#add_preparation/3) # add\_preparation(dsl\_state, ref, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L257) ``` @spec add_preparation( Spark.Dsl.Builder.input(), ref :: module() | {module(), Keyword.t()}, opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds a preparation [](Ash.Resource.Builder.html#add_relationship/5) # add\_relationship(dsl\_state, type, name, destination, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L124) ``` @spec add_relationship( Spark.Dsl.Builder.input(), type :: Ash.Resource.Relationships.type(), name :: atom(), destination :: module(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an action [](Ash.Resource.Builder.html#add_update_timestamp/3) # add\_update\_timestamp(dsl\_state, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L393) ``` @spec add_update_timestamp( Spark.Dsl.Builder.input(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an update\_timestamp [](Ash.Resource.Builder.html#build_action/3) # build\_action(type, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L76) ``` @spec build_action( type :: Ash.Resource.Actions.action_type(), name :: atom(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.Actions.action()} | {:error, term()} ``` Builds an action [](Ash.Resource.Builder.html#build_action_argument/3) # build\_action\_argument(name, type, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L306) ``` @spec build_action_argument(name :: atom(), type :: Ash.Type.t(), opts :: Keyword.t()) :: {:ok, Ash.Resource.Actions.Argument.t()} | {:error, term()} ``` Builds an action argument [](Ash.Resource.Builder.html#build_action_change/2) # build\_action\_change(change, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L350) ``` @spec build_action_change(change :: Ash.Resource.Change.ref(), opts :: Keyword.t()) :: {:ok, Ash.Resource.Change.t()} | {:error, term()} ``` Builds an action change [](Ash.Resource.Builder.html#build_action_metadata/3) # build\_action\_metadata(name, type, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L335) ``` @spec build_action_metadata(name :: atom(), type :: Ash.Type.t(), opts :: Keyword.t()) :: {:ok, Ash.Resource.Actions.Metadata.t()} | {:error, term()} ``` Builds an action metadata [](Ash.Resource.Builder.html#build_action_validation/2) # build\_action\_validation(validation, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L365) ``` @spec build_action_validation( change :: Ash.Resource.Validation.ref(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.Validation.t()} | {:error, term()} ``` Builds an action validation [](Ash.Resource.Builder.html#build_aggregate/4) # build\_aggregate(name, kind, relationship\_path, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L607) ``` @spec build_aggregate( name :: atom(), kind :: Ash.Query.Aggregate.kind(), relationship_path :: atom() | [atom()], opts :: Keyword.t() ) :: {:ok, Ash.Resource.Aggregate.t()} | {:error, term()} ``` Builds a calculation with the given name, type, and options [](Ash.Resource.Builder.html#build_attribute/3) # build\_attribute(name, type, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L494) ``` @spec build_attribute(name :: atom(), type :: Ash.Type.t(), opts :: Keyword.t()) :: {:ok, Ash.Resource.Attribute.t()} | {:error, term()} ``` Builds an attribute with the given name, type, and options [](Ash.Resource.Builder.html#build_calculation/4) # build\_calculation(name, type, calculation, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L550) ``` @spec build_calculation( name :: atom(), type :: Ash.Type.t(), calculation :: module() | {module(), Keyword.t()}, opts :: Keyword.t() ) :: {:ok, Ash.Resource.Calculation.t()} | {:error, term()} ``` Builds a calculation with the given name, type, and options [](Ash.Resource.Builder.html#build_calculation_argument/3) # build\_calculation\_argument(name, type, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L321) ``` @spec build_calculation_argument( name :: atom(), type :: Ash.Type.t(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.Calculation.Argument.t()} | {:error, term()} ``` Builds a calculation argument [](Ash.Resource.Builder.html#build_calculation_interface/2) # build\_calculation\_interface(name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L699) ``` @spec build_calculation_interface(name :: atom(), opts :: Keyword.t()) :: {:ok, Ash.Resource.CalculationInterface.t()} | {:error, term()} ``` Builds an calculation interface with the given name, type, and options [](Ash.Resource.Builder.html#build_change/2) # build\_change(ref, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L239) ``` @spec build_change( ref :: module() | {module(), Keyword.t()}, opts :: Keyword.t() ) :: {:ok, Ash.Resource.Change.t()} | {:error, term()} ``` Builds a change [](Ash.Resource.Builder.html#build_create_timestamp/2) # build\_create\_timestamp(name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L446) ``` @spec build_create_timestamp(name :: atom(), opts :: Keyword.t()) :: {:ok, Ash.Resource.Attribute.t()} | {:error, term()} ``` Builds an create\_timestamp with the given name, type, and options [](Ash.Resource.Builder.html#build_identity/3) # build\_identity(name, fields, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L192) ``` @spec build_identity( name :: atom(), fields :: atom() | [atom()], opts :: Keyword.t() ) :: {:ok, Ash.Resource.Identity.t()} | {:error, term()} ``` Builds an action [](Ash.Resource.Builder.html#build_interface/2) # build\_interface(name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L653) ``` @spec build_interface(name :: atom(), opts :: Keyword.t()) :: {:ok, Ash.Resource.Interface.t()} | {:error, term()} ``` Builds an interface with the given name, type, and options [](Ash.Resource.Builder.html#build_pagination/1) # build\_pagination(opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L291) ``` @spec build_pagination(pts :: Keyword.t()) :: {:ok, Ash.Resource.Actions.Read.Pagination.t()} | {:error, term()} ``` Builds a pagination object [](Ash.Resource.Builder.html#build_preparation/2) # build\_preparation(ref, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L277) ``` @spec build_preparation( ref :: module() | {module(), Keyword.t()}, opts :: Keyword.t() ) :: {:ok, Ash.Resource.Preparation.t()} | {:error, term()} ``` Builds a preparation [](Ash.Resource.Builder.html#build_relationship/4) # build\_relationship(type, name, destination, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L140) ``` @spec build_relationship( type :: Ash.Resource.Relationships.type(), name :: atom(), destination :: module(), opts :: Keyword.t() ) :: {:ok, Ash.Resource.Relationships.relationship()} | {:error, term()} ``` Builds a relationship [](Ash.Resource.Builder.html#build_update_timestamp/2) # build\_update\_timestamp(name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L404) ``` @spec build_update_timestamp(name :: atom(), opts :: Keyword.t()) :: {:ok, Ash.Resource.Attribute.t()} | {:error, term()} ``` Builds an update\_timestamp with the given name, type, and options [](Ash.Resource.Builder.html#prepend_action/4) # prepend\_action(dsl\_state, type, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/builder.ex#L57) ``` @spec prepend_action( Spark.Dsl.Builder.input(), type :: Ash.Resource.Actions.action_type(), name :: atom(), opts :: Keyword.t() ) :: Spark.Dsl.Builder.result() ``` Builds and adds an action to the front of the actions list [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Calculation.Argument (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/argument.ex#L1 "View Source") An argument to a calculation # [](Ash.Resource.Calculation.Argument.html#summary)Summary ## [Types](Ash.Resource.Calculation.Argument.html#types) [t()](Ash.Resource.Calculation.Argument.html#t:t/0) ## [Functions](Ash.Resource.Calculation.Argument.html#functions) [schema()](Ash.Resource.Calculation.Argument.html#schema/0) # [](Ash.Resource.Calculation.Argument.html#types)Types [](Ash.Resource.Calculation.Argument.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/argument.ex#L10) ``` @type t() :: %Ash.Resource.Calculation.Argument{ allow_expr?: boolean(), allow_nil?: boolean(), constraints: keyword(), default: any(), name: atom(), type: Ash.Type.t() } ``` # [](Ash.Resource.Calculation.Argument.html#functions)Functions [](Ash.Resource.Calculation.Argument.html#schema/0) # schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/argument.ex#L53) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Calculation.Builtins (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/builtins.ex#L1 "View Source") Built in calculations that are automatically imported in the calculations section # [](Ash.Resource.Calculation.Builtins.html#summary)Summary ## [Functions](Ash.Resource.Calculation.Builtins.html#functions) [concat(keys, separator \\\\ "")](Ash.Resource.Calculation.Builtins.html#concat/2) An example concatenation calculation, that accepts the delimiter as an argument # [](Ash.Resource.Calculation.Builtins.html#functions)Functions [](Ash.Resource.Calculation.Builtins.html#concat/2) # concat(keys, separator \\\\ "") [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/builtins.ex#L12) ``` @spec concat(keys :: [atom()], separator :: String.t()) :: Ash.Resource.Calculation.ref() ``` An example concatenation calculation, that accepts the delimiter as an argument ## [](Ash.Resource.Calculation.Builtins.html#concat/2-examples)Examples ``` calculate :full_name, :string, concat([:first_name, :last_name], " ") ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Calculation.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L95 "View Source") The context and arguments of a calculation # [](Ash.Resource.Calculation.Context.html#summary)Summary ## [Types](Ash.Resource.Calculation.Context.html#types) [t()](Ash.Resource.Calculation.Context.html#t:t/0) # [](Ash.Resource.Calculation.Context.html#types)Types [](Ash.Resource.Calculation.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L113) ``` @type t() :: %Ash.Resource.Calculation.Context{ actor: term() | nil, arguments: map(), authorize?: boolean(), constraints: Keyword.t(), domain: module(), resource: module(), source_context: map(), tenant: term(), tracer: module() | nil, type: Ash.Type.t() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Calculation behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L1 "View Source") The behaviour for defining a module calculation, and the struct for storing a defined calculation. # [](Ash.Resource.Calculation.html#summary)Summary ## [Types](Ash.Resource.Calculation.html#types) [opts()](Ash.Resource.Calculation.html#t:opts/0) [ref()](Ash.Resource.Calculation.html#t:ref/0) [t()](Ash.Resource.Calculation.html#t:t/0) ## [Callbacks](Ash.Resource.Calculation.html#callbacks) [calculate(records, opts, context)](Ash.Resource.Calculation.html#c:calculate/3) [describe(opts)](Ash.Resource.Calculation.html#c:describe/1) [expression(opts, context)](Ash.Resource.Calculation.html#c:expression/2) [has\_expression?()](Ash.Resource.Calculation.html#c:has_expression?/0) [init(opts)](Ash.Resource.Calculation.html#c:init/1) [load(query, opts, context)](Ash.Resource.Calculation.html#c:load/3) [strict\_loads?()](Ash.Resource.Calculation.html#c:strict_loads?/0) ## [Functions](Ash.Resource.Calculation.html#functions) [expr\_calc(expr)](Ash.Resource.Calculation.html#expr_calc/1) [schema()](Ash.Resource.Calculation.html#schema/0) # [](Ash.Resource.Calculation.html#types)Types [](Ash.Resource.Calculation.html#t:opts/0) # opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L181) ``` @type opts() :: Keyword.t() ``` [](Ash.Resource.Calculation.html#t:ref/0) # ref() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L142) ``` @type ref() :: {module(), Keyword.t()} | module() ``` [](Ash.Resource.Calculation.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L127) ``` @type t() :: %Ash.Resource.Calculation{ allow_nil?: boolean(), arguments: [Ash.Resource.Calculation.Argument.t()], async?: boolean(), calculation: module() | {module(), keyword()}, constraints: keyword(), description: nil | String.t(), filterable?: boolean(), load: keyword(), name: atom(), public?: boolean(), sensitive?: term(), sortable?: boolean(), type: nil | Ash.Type.t() } ``` # [](Ash.Resource.Calculation.html#callbacks)Callbacks [](Ash.Resource.Calculation.html#c:calculate/3) # calculate(records, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L186) ``` @callback calculate( records :: [Ash.Resource.record()], opts :: opts(), context :: Ash.Resource.Calculation.Context.t() ) :: {:ok, [term()]} | [term()] | {:error, term()} | :unknown ``` [](Ash.Resource.Calculation.html#c:describe/1) # describe(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L184) ``` @callback describe(opts :: opts()) :: String.t() ``` [](Ash.Resource.Calculation.html#c:expression/2) # expression(opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L188) ``` @callback expression(opts :: opts(), context :: Ash.Resource.Calculation.Context.t()) :: any() ``` [](Ash.Resource.Calculation.html#c:has_expression?/0) # has\_expression?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L192) ``` @callback has_expression?() :: boolean() ``` [](Ash.Resource.Calculation.html#c:init/1) # init(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L183) ``` @callback init(opts :: opts()) :: {:ok, opts()} | {:error, term()} ``` [](Ash.Resource.Calculation.html#c:load/3) # load(query, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L189) ``` @callback load( query :: Ash.Query.t(), opts :: opts(), context :: Ash.Resource.Calculation.Context.t() ) :: atom() | [atom()] | Keyword.t() ``` [](Ash.Resource.Calculation.html#c:strict_loads?/0) # strict\_loads?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L191) ``` @callback strict_loads?() :: boolean() ``` # [](Ash.Resource.Calculation.html#functions)Functions [](Ash.Resource.Calculation.html#expr_calc/1) # expr\_calc(expr) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L198) [](Ash.Resource.Calculation.html#schema/0) # schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/calculation.ex#L196) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.CalculationInterface (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation_interface.ex#L1 "View Source") Represents a function that evaluates a calculation in a resource's code interface # [](Ash.Resource.CalculationInterface.html#summary)Summary ## [Types](Ash.Resource.CalculationInterface.html#types) [t()](Ash.Resource.CalculationInterface.html#t:t/0) ## [Functions](Ash.Resource.CalculationInterface.html#functions) [schema()](Ash.Resource.CalculationInterface.html#schema/0) [transform(interface)](Ash.Resource.CalculationInterface.html#transform/1) # [](Ash.Resource.CalculationInterface.html#types)Types [](Ash.Resource.CalculationInterface.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation_interface.ex#L7) ``` @type t() :: %Ash.Resource.CalculationInterface{ args: term(), calculation: term(), name: term() } ``` # [](Ash.Resource.CalculationInterface.html#functions)Functions [](Ash.Resource.CalculationInterface.html#schema/0) # schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation_interface.ex#L29) [](Ash.Resource.CalculationInterface.html#transform/1) # transform(interface) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation_interface.ex#L31) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Calculation.LoadAttribute (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L1 "View Source") Loads an attribute as a calculation. Can be used to load the same attribute with different load statements applied. # [](Ash.Resource.Calculation.LoadAttribute.html#summary)Summary ## [Functions](Ash.Resource.Calculation.LoadAttribute.html#functions) [calculate(list, opts, context)](Ash.Resource.Calculation.LoadAttribute.html#calculate/3) Callback implementation for [`Ash.Resource.Calculation.calculate/3`](Ash.Resource.Calculation.html#c:calculate/3). [describe(opts)](Ash.Resource.Calculation.LoadAttribute.html#describe/1) Callback implementation for [`Ash.Resource.Calculation.describe/1`](Ash.Resource.Calculation.html#c:describe/1). [has\_calculate?()](Ash.Resource.Calculation.LoadAttribute.html#has_calculate?/0) [has\_expression?()](Ash.Resource.Calculation.LoadAttribute.html#has_expression?/0) Callback implementation for [`Ash.Resource.Calculation.has_expression?/0`](Ash.Resource.Calculation.html#c:has_expression?/0). [init(opts)](Ash.Resource.Calculation.LoadAttribute.html#init/1) Callback implementation for [`Ash.Resource.Calculation.init/1`](Ash.Resource.Calculation.html#c:init/1). [load(query, opts, arg3)](Ash.Resource.Calculation.LoadAttribute.html#load/3) Callback implementation for [`Ash.Resource.Calculation.load/3`](Ash.Resource.Calculation.html#c:load/3). [strict\_loads?()](Ash.Resource.Calculation.LoadAttribute.html#strict_loads?/0) Callback implementation for [`Ash.Resource.Calculation.strict_loads?/0`](Ash.Resource.Calculation.html#c:strict_loads?/0). # [](Ash.Resource.Calculation.LoadAttribute.html#functions)Functions [](Ash.Resource.Calculation.LoadAttribute.html#calculate/3) # calculate(list, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L13) Callback implementation for [`Ash.Resource.Calculation.calculate/3`](Ash.Resource.Calculation.html#c:calculate/3). [](Ash.Resource.Calculation.LoadAttribute.html#describe/1) # describe(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L7) Callback implementation for [`Ash.Resource.Calculation.describe/1`](Ash.Resource.Calculation.html#c:describe/1). [](Ash.Resource.Calculation.LoadAttribute.html#has_calculate?/0) # has\_calculate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L1) [](Ash.Resource.Calculation.LoadAttribute.html#has_expression?/0) # has\_expression?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L1) Callback implementation for [`Ash.Resource.Calculation.has_expression?/0`](Ash.Resource.Calculation.html#c:has_expression?/0). [](Ash.Resource.Calculation.LoadAttribute.html#init/1) # init(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L7) Callback implementation for [`Ash.Resource.Calculation.init/1`](Ash.Resource.Calculation.html#c:init/1). [](Ash.Resource.Calculation.LoadAttribute.html#load/3) # load(query, opts, arg3) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L9) Callback implementation for [`Ash.Resource.Calculation.load/3`](Ash.Resource.Calculation.html#c:load/3). [](Ash.Resource.Calculation.LoadAttribute.html#strict_loads?/0) # strict\_loads?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_attribute.ex#L1) Callback implementation for [`Ash.Resource.Calculation.strict_loads?/0`](Ash.Resource.Calculation.html#c:strict_loads?/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Calculation.LoadRelationship (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L1 "View Source") Loads a relationship as a calculation. Can be used to load the same relationship with a different query. # [](Ash.Resource.Calculation.LoadRelationship.html#summary)Summary ## [Functions](Ash.Resource.Calculation.LoadRelationship.html#functions) [calculate(results, opts, context)](Ash.Resource.Calculation.LoadRelationship.html#calculate/3) Callback implementation for [`Ash.Resource.Calculation.calculate/3`](Ash.Resource.Calculation.html#c:calculate/3). [describe(opts)](Ash.Resource.Calculation.LoadRelationship.html#describe/1) Callback implementation for [`Ash.Resource.Calculation.describe/1`](Ash.Resource.Calculation.html#c:describe/1). [has\_calculate?()](Ash.Resource.Calculation.LoadRelationship.html#has_calculate?/0) [has\_expression?()](Ash.Resource.Calculation.LoadRelationship.html#has_expression?/0) Callback implementation for [`Ash.Resource.Calculation.has_expression?/0`](Ash.Resource.Calculation.html#c:has_expression?/0). [init(opts)](Ash.Resource.Calculation.LoadRelationship.html#init/1) Callback implementation for [`Ash.Resource.Calculation.init/1`](Ash.Resource.Calculation.html#c:init/1). [load(query, opts, arg3)](Ash.Resource.Calculation.LoadRelationship.html#load/3) Callback implementation for [`Ash.Resource.Calculation.load/3`](Ash.Resource.Calculation.html#c:load/3). [strict\_loads?()](Ash.Resource.Calculation.LoadRelationship.html#strict_loads?/0) Callback implementation for [`Ash.Resource.Calculation.strict_loads?/0`](Ash.Resource.Calculation.html#c:strict_loads?/0). # [](Ash.Resource.Calculation.LoadRelationship.html#functions)Functions [](Ash.Resource.Calculation.LoadRelationship.html#calculate/3) # calculate(results, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L19) Callback implementation for [`Ash.Resource.Calculation.calculate/3`](Ash.Resource.Calculation.html#c:calculate/3). [](Ash.Resource.Calculation.LoadRelationship.html#describe/1) # describe(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L7) Callback implementation for [`Ash.Resource.Calculation.describe/1`](Ash.Resource.Calculation.html#c:describe/1). [](Ash.Resource.Calculation.LoadRelationship.html#has_calculate?/0) # has\_calculate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L1) [](Ash.Resource.Calculation.LoadRelationship.html#has_expression?/0) # has\_expression?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L1) Callback implementation for [`Ash.Resource.Calculation.has_expression?/0`](Ash.Resource.Calculation.html#c:has_expression?/0). [](Ash.Resource.Calculation.LoadRelationship.html#init/1) # init(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L7) Callback implementation for [`Ash.Resource.Calculation.init/1`](Ash.Resource.Calculation.html#c:init/1). [](Ash.Resource.Calculation.LoadRelationship.html#load/3) # load(query, opts, arg3) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L9) Callback implementation for [`Ash.Resource.Calculation.load/3`](Ash.Resource.Calculation.html#c:load/3). [](Ash.Resource.Calculation.LoadRelationship.html#strict_loads?/0) # strict\_loads?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/calculation/load_relationship.ex#L1) Callback implementation for [`Ash.Resource.Calculation.strict_loads?/0`](Ash.Resource.Calculation.html#c:strict_loads?/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.Builtins (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L1 "View Source") Built in changes that are available to all resources The functions in this module are imported by default in the actions section. # [](Ash.Resource.Change.Builtins.html#summary)Summary ## [Functions](Ash.Resource.Change.Builtins.html#functions) [after\_action(callback, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#after_action/2) Directly attach an `after_action` function to the current change. [after\_transaction(callback, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#after_transaction/2) Directly attach an `after_transaction` function to the current change. [atomic\_update(attribute, expr, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#atomic_update/3) Updates an attribute using an expression. See [`Ash.Changeset.atomic_update/3`](Ash.Changeset.html#atomic_update/3) for more. [before\_action(callback, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#before_action/2) Directly attach a `before_action` function to the current change. [before\_transaction(callback, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#before_transaction/2) Directly attach a `before_transaction` function to the current change. [cascade\_destroy(relationship, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#cascade_destroy/2) Cascade this resource's destroy action to a related resource's destroy action. [cascade\_update(relationship, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#cascade_update/2) Cascade a resource's update action to a related resource's update action. [debug\_log(label \\\\ nil)](Ash.Resource.Change.Builtins.html#debug_log/1) [ensure\_selected(value)](Ash.Resource.Change.Builtins.html#ensure_selected/1) Passes the provided value into [`Ash.Changeset.ensure_selected/2`](Ash.Changeset.html#ensure_selected/2) [filter(filter)](Ash.Resource.Change.Builtins.html#filter/1) Applies a filter to the changeset. Has no effect for create actions. [get\_and\_lock(lock, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#get_and_lock/2) Re-fetches the record being updated and locks it with the given type. [get\_and\_lock\_for\_update(opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#get_and_lock_for_update/1) Re-fetches the record being updated and locks it for update. [increment(attribute, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#increment/2) Increments an attribute's value by the amount specified, which defaults to 1. [load(value)](Ash.Resource.Change.Builtins.html#load/1) Passes the provided value into `Ash.load` after the action has completed. [manage\_relationship(argument, relationship\_name \\\\ nil, opts)](Ash.Resource.Change.Builtins.html#manage_relationship/3) Calls [`Ash.Changeset.manage_relationship/4`](Ash.Changeset.html#manage_relationship/4) with the changeset and relationship provided, using the value provided for the named argument. [optimistic\_lock(attribute)](Ash.Resource.Change.Builtins.html#optimistic_lock/1) Apply an "optimistic lock" on a record being updated or destroyed. [prevent\_change(attribute)](Ash.Resource.Change.Builtins.html#prevent_change/1) Clears a change off of the changeset before the action runs. [relate\_actor(relationship, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#relate_actor/2) Relates the actor to the data being changed, as the provided relationship. [select(value)](Ash.Resource.Change.Builtins.html#select/1) Passes the provided value into [`Ash.Changeset.select/3`](Ash.Changeset.html#select/3) [set\_attribute(attribute, value, opts \\\\ \[\])](Ash.Resource.Change.Builtins.html#set_attribute/3) Sets the attribute to the value provided. [set\_context(context)](Ash.Resource.Change.Builtins.html#set_context/1) Merges the given query context. [set\_new\_attribute(attribute, value)](Ash.Resource.Change.Builtins.html#set_new_attribute/2) Sets the attribute to the value provided if the attribute is not already being changed. [update\_change(attribute, function)](Ash.Resource.Change.Builtins.html#update_change/2) Updates an existing attribute change by applying a function to it. # [](Ash.Resource.Change.Builtins.html#functions)Functions [](Ash.Resource.Change.Builtins.html#after_action/2) # after\_action(callback, opts \\\\ \[]) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L389) Directly attach an `after_action` function to the current change. See [`Ash.Changeset.after_action/3`](Ash.Changeset.html#after_action/3) for more information. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. ## [](Ash.Resource.Change.Builtins.html#after_action/2-example)Example ``` change after_action(fn changeset, record, _context -> Logger.debug("Successfully executed action #{changeset.action.name} on #{inspect(changeset.resource)}") {:ok, record} end) ``` [](Ash.Resource.Change.Builtins.html#after_transaction/2) # after\_transaction(callback, opts \\\\ \[]) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L419) Directly attach an `after_transaction` function to the current change. See [`Ash.Changeset.after_transaction/3`](Ash.Changeset.html#after_transaction/3) for more information. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. ## [](Ash.Resource.Change.Builtins.html#after_transaction/2-example)Example ``` change after_transaction(fn changeset, {:ok, record}, _context -> Logger.debug("Successfully executed transaction for action #{changeset.action.name} on #{inspect(changeset.resource)}") {:ok, record} changeset, {:error, reason}, _context -> Logger.debug("Failed to execute transaction for action #{changeset.action.name} on #{inspect(changeset.resource)}, reason: #{inspect(reason)}") {:error, reason} end) ``` [](Ash.Resource.Change.Builtins.html#atomic_update/3) # atomic\_update(attribute, expr, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L170) ``` @spec atomic_update(attribute :: atom(), expr :: Ash.Expr.t(), opts :: Keyword.t()) :: Ash.Resource.Change.ref() ``` Updates an attribute using an expression. See [`Ash.Changeset.atomic_update/3`](Ash.Changeset.html#atomic_update/3) for more. Options: - `:cast_atomic?` - set to `false` to ignore atomic type casting logic. Defaults to `true`. [](Ash.Resource.Change.Builtins.html#before_action/2) # before\_action(callback, opts \\\\ \[]) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L446) Directly attach a `before_action` function to the current change. See [`Ash.Changeset.before_action/3`](Ash.Changeset.html#before_action/3) for more information. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. ## [](Ash.Resource.Change.Builtins.html#before_action/2-example)Example ``` change before_action(fn changeset, _context -> Logger.debug("About to execute #{changeset.action.name} on #{inspect(changeset.resource)}") changeset end) ``` [](Ash.Resource.Change.Builtins.html#before_transaction/2) # before\_transaction(callback, opts \\\\ \[]) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L473) Directly attach a `before_transaction` function to the current change. See [`Ash.Changeset.before_transaction/3`](Ash.Changeset.html#before_transaction/3) for more information. Provide the option `prepend?: true` to place the hook before all other hooks instead of after. ## [](Ash.Resource.Change.Builtins.html#before_transaction/2-example)Example ``` change before_transaction(fn changeset, _context -> Logger.debug("About to execute transaction for #{changeset.action.name} on #{inspect(changeset.resource)}") changeset end) ``` [](Ash.Resource.Change.Builtins.html#cascade_destroy/2) # cascade\_destroy(relationship, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L330) Cascade this resource's destroy action to a related resource's destroy action. Adds an after-action hook that explicitly calls destroy on any records related via the named relationship. It will optimise for bulk destroys where possible. #### Beware database constraints Think carefully before using this change with data layers which enforce referential integrity (ie PostgreSQL and SQLite) and you may need to defer constraints for the relationship in question. See also: 1. [`postgres.references.reference.deferrable` DSL](../ash_postgres/dsl-ashpostgres-datalayer.html#postgres-references-reference-deferrable) 2. [`sqlite.references.reference.deferrable` DSL](../ash_sqlite/dsl-ashsqlite-datalayer.html#sqlite-references-reference-deferrable) 3. [PostgreSQL's `SET CONSTRAINTS` documentation](https://www.postgresql.org/docs/current/sql-set-constraints.html) 4. [SQLite's `PRAGMA defer_foreign_keys` documentation](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) #### Cascading notifications By default notifications are disabled for the related destroy. This is to avoid potentially sending a **lot** of notifications for high-cardinality relationships. ## [](Ash.Resource.Change.Builtins.html#cascade_destroy/2-options)Options - `:relationship` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Required. The name of the relationship to work on - `:action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the destroy action to call on the related resource. Uses the primary destroy by default. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the read action to call on the related resource to find results to be destroyed - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Return notifications for all destroyed records? The default value is `false`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - ## [](Ash.Resource.Change.Builtins.html#cascade_destroy/2-example)Example ``` change cascade_destroy(:relationship) ``` [](Ash.Resource.Change.Builtins.html#cascade_update/2) # cascade\_update(relationship, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L370) Cascade a resource's update action to a related resource's update action. Adds an after-action hook that explicitly calls update on any records related via the named relationship. It will optimise for bulk updates where possible. Allows you to copy fields from the arguments or changes to the destination, this way you can cascade a bunch of changes downstream. #### Beware database constraints Think carefully before using this change with data layers which enforce referential integrity (ie PostgreSQL and SQLite) and you may need to defer constraints for the relationship in question. See also: 1. [`postgres.references.reference.deferrable` DSL](../ash_postgres/dsl-ashpostgres-datalayer.html#postgres-references-reference-deferrable) 2. [`sqlite.references.reference.deferrable` DSL](../ash_sqlite/dsl-ashsqlite-datalayer.html#sqlite-references-reference-deferrable) 3. [PostgreSQL's `SET CONSTRAINTS` documentation](https://www.postgresql.org/docs/current/sql-set-constraints.html) 4. [SQLite's `PRAGMA defer_foreign_keys` documentation](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) #### Cascading notifications By default notifications are disabled for the related updates. This is to avoid potentially sending a **lot** of notifications for high-cardinality relationships. ## [](Ash.Resource.Change.Builtins.html#cascade_update/2-options)Options - `:relationship` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Required. The name of the relationship to work on - `:action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the update action to call on the related resource. Uses the primary update by default. - `:copy_inputs` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A list of fields to copy &amp; pass on to the downstream update. The source action cannot be atomic. The default value is `[]`. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the read action to call on the related resource to find results to be updated - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Return notifications for all updated records? The default value is `false`. - `:domain` ([`Ash.Domain`](Ash.Domain.html)) - ## [](Ash.Resource.Change.Builtins.html#cascade_update/2-example)Example ``` change cascade_update(:relationship1) change cascade_update(:relationship2, copy_inputs: [:field1, :field2]) ``` [](Ash.Resource.Change.Builtins.html#debug_log/1) # debug\_log(label \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L40) ``` @spec debug_log(label :: String.t() | nil) :: Ash.Resource.Change.ref() ``` [](Ash.Resource.Change.Builtins.html#ensure_selected/1) # ensure\_selected(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L294) ``` @spec ensure_selected(select :: atom() | [atom()]) :: Ash.Resource.Change.ref() ``` Passes the provided value into [`Ash.Changeset.ensure_selected/2`](Ash.Changeset.html#ensure_selected/2) If the value is not already selected, this makes sure it is. Does not deselect anything else. ## [](Ash.Resource.Change.Builtins.html#ensure_selected/1-example)Example ``` change ensure_selected([:necessary_field]) ``` [](Ash.Resource.Change.Builtins.html#filter/1) # filter(filter) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L14) ``` @spec filter(expr :: Ash.Expr.t()) :: Ash.Resource.Change.ref() ``` Applies a filter to the changeset. Has no effect for create actions. This ensures that only things matching the provided filter are updated or destroyed. [](Ash.Resource.Change.Builtins.html#get_and_lock/2) # get\_and\_lock(lock, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L88) Re-fetches the record being updated and locks it with the given type. This happens in a `before_action` hook (so that it is done as part of the transaction). If your resource has global validations (in the top level `validations` block), you may want to add `delay_global_validations? true` to your action to ensure they happen on the locked record. ## [](Ash.Resource.Change.Builtins.html#get_and_lock/2-options)Options - `:skip_atomic?` - set to `true` to skip in the case that the update is done atomically. Defaults to `false`. [](Ash.Resource.Change.Builtins.html#get_and_lock_for_update/1) # get\_and\_lock\_for\_update(opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L70) ``` @spec get_and_lock_for_update(opts :: Keyword.t()) :: Ash.Resource.Change.ref() ``` Re-fetches the record being updated and locks it for update. Only usable with data layers that support locking `:for_update`. This happens in a `before_action` hook (so that it is done as part of the transaction). If your resource has global validations (in the top level `validations` block), you may want to add `delay_global_validations? true` to your action to ensure they happen on the locked record. ## [](Ash.Resource.Change.Builtins.html#get_and_lock_for_update/1-options)Options - `:skip_atomic?` - set to `true` to skip in the case that the update is done atomically. Defaults to `false`. [](Ash.Resource.Change.Builtins.html#increment/2) # increment(attribute, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L118) ``` @spec increment(attribute :: atom(), opts :: Keyword.t()) :: Ash.Resource.Change.ref() ``` Increments an attribute's value by the amount specified, which defaults to 1. Options: - `:amount` - Defaults to 1 - `:overflow_limit` - Defaults to `nil`. If the value is over the overflow limit it will roll-over to the amount being incremented by (for common database limit support) [](Ash.Resource.Change.Builtins.html#load/1) # load(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L261) ``` @spec load(load :: term()) :: Ash.Resource.Change.ref() ``` Passes the provided value into `Ash.load` after the action has completed. ## [](Ash.Resource.Change.Builtins.html#load/1-example)Example ``` change load(:comments) change load([:friend_count, :friends]) ``` [](Ash.Resource.Change.Builtins.html#manage_relationship/3) # manage\_relationship(argument, relationship\_name \\\\ nil, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L228) ``` @spec manage_relationship( argument :: atom(), relationship_name :: atom() | nil, opts :: Keyword.t() ) :: Ash.Resource.Change.ref() ``` Calls [`Ash.Changeset.manage_relationship/4`](Ash.Changeset.html#manage_relationship/4) with the changeset and relationship provided, using the value provided for the named argument. If relationship\_name is not specified, it is assumed to be the same as the argument. For information on the available options, see [`Ash.Changeset.manage_relationship/4`](Ash.Changeset.html#manage_relationship/4). ## [](Ash.Resource.Change.Builtins.html#manage_relationship/3-examples)Examples ``` change manage_relationship(:comments, type: :append) change manage_relationship(:remove_comments, :comments, type: :remove) ``` [](Ash.Resource.Change.Builtins.html#optimistic_lock/1) # optimistic\_lock(attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L49) Apply an "optimistic lock" on a record being updated or destroyed. See [`Ash.Resource.Change.OptimisticLock`](Ash.Resource.Change.OptimisticLock.html) for more. [](Ash.Resource.Change.Builtins.html#prevent_change/1) # prevent\_change(attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L206) ``` @spec prevent_change(attribute :: atom()) :: Ash.Resource.Change.ref() ``` Clears a change off of the changeset before the action runs. Does not fail if it is being changed, but ensures it is cleared just before the action. Can be useful if a change is only used in validations but shouldn't ultimately be written to the data layer. ## [](Ash.Resource.Change.Builtins.html#prevent_change/1-examples)Examples ``` change prevent_change(:email) ``` [](Ash.Resource.Change.Builtins.html#relate_actor/2) # relate\_actor(relationship, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L30) ``` @spec relate_actor(relationship :: atom(), opts :: Keyword.t()) :: Ash.Resource.Change.ref() ``` Relates the actor to the data being changed, as the provided relationship. ## [](Ash.Resource.Change.Builtins.html#relate_actor/2-options)Options - `:allow_nil?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to allow the actor to be nil, in which case nothing will happen. The default value is `false`. - `:field` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The field of the actor to set the relationship to ## [](Ash.Resource.Change.Builtins.html#relate_actor/2-examples)Examples ``` change relate_actor(:owner, allow_nil?: true) ``` [](Ash.Resource.Change.Builtins.html#select/1) # select(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L280) ``` @spec select(select :: atom() | [atom()]) :: Ash.Resource.Change.ref() ``` Passes the provided value into [`Ash.Changeset.select/3`](Ash.Changeset.html#select/3) Keep in mind, this will *limit* the fields that are selected. You may want [`ensure_selected/1`](Ash.Resource.Change.Builtins.html#ensure_selected/1) if you want to make sure that something is selected, without deselecting anything else. Selecting in changesets does not actually do a select in the data layer. It nils out any fields that were not selected after completing the action. This can be useful if you are writing policies that have to do with specific fields being selected. ## [](Ash.Resource.Change.Builtins.html#select/1-example)Example ``` change select([:name]) ``` [](Ash.Resource.Change.Builtins.html#set_attribute/3) # set\_attribute(attribute, value, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L152) ``` @spec set_attribute( attribute :: atom(), (-> term()) | {:_arg, :status} | term(), opts :: Keyword.t() ) :: Ash.Resource.Change.ref() ``` Sets the attribute to the value provided. If a zero argument function is provided, it is called to determine the value. Use `arg(:argument_name)` to use the value of the given argument. If the argument is not supplied then nothing happens. ## [](Ash.Resource.Change.Builtins.html#set_attribute/3-options)Options - `:set_when_nil?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - When false, decline setting the attribute if it is nil. The default value is `true`. - `:new?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - When true, sets the attribute to the value provided if the attribute is not already being changed. The default value is `false`. ## [](Ash.Resource.Change.Builtins.html#set_attribute/3-examples)Examples ``` change set_attribute(:active, false) change set_attribute(:opened_at, &DateTime.utc_now/0) change set_attribute(:status, arg(:status)) change set_attribute(:encrypted_data, arg(:data), set_when_nil?: false) ``` [](Ash.Resource.Change.Builtins.html#set_context/1) # set\_context(context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L248) ``` @spec set_context(context :: map() | mfa()) :: Ash.Resource.Change.ref() ``` Merges the given query context. If an MFA is provided, it will be called with the changeset. The MFA should return `{:ok, context_to_be_merged}` or `{:error, term}` ## [](Ash.Resource.Change.Builtins.html#set_context/1-examples)Examples ``` change set_context(%{something_used_internally: true}) change set_context({MyApp.Context, :set_context, []}) ``` [](Ash.Resource.Change.Builtins.html#set_new_attribute/2) # set\_new\_attribute(attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L190) ``` @spec set_new_attribute( relationship :: atom(), (-> term()) | {:_arg, :status} | term() ) :: Ash.Resource.Change.ref() ``` Sets the attribute to the value provided if the attribute is not already being changed. If a zero argument function is provided, it is called to determine the value. Use `arg(:argument_name)` to use the value of the given argument. If the argument is not supplied then nothing happens. ## [](Ash.Resource.Change.Builtins.html#set_new_attribute/2-examples)Examples ``` change set_new_attribute(:active, false) change set_new_attribute(:opened_at, &DateTime.utc_now/0) change set_new_attribute(:status, arg(:status)) ``` [](Ash.Resource.Change.Builtins.html#update_change/2) # update\_change(attribute, function) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/builtins.ex#L98) Updates an existing attribute change by applying a function to it. The update function gets called with the value already cast to the correct type, and only gets called on valid changesets, so the value is guaranteed to have passed validations and constraints. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.CascadeDestroy (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/cascade_destroy.ex#L1 "View Source") Cascade a resource's destroy action to a related resource's destroy action. Adds an after-action hook that explicitly calls destroy on any records related via the named relationship. It will optimise for bulk destroys where possible. #### Beware database constraints Think carefully before using this change with data layers which enforce referential integrity (ie PostgreSQL and SQLite) and you may need to defer constraints for the relationship in question. See also: 1. [`postgres.references.reference.deferrable` DSL](../ash_postgres/dsl-ashpostgres-datalayer.html#postgres-references-reference-deferrable) 2. [`sqlite.references.reference.deferrable` DSL](../ash_sqlite/dsl-ashsqlite-datalayer.html#sqlite-references-reference-deferrable) 3. [PostgreSQL's `SET CONSTRAINTS` documentation](https://www.postgresql.org/docs/current/sql-set-constraints.html) 4. [SQLite's `PRAGMA defer_foreign_keys` documentation](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) #### Cascading notifications By default notifications are disabled for the related destroy. This is to avoid potentially sending a **lot** of notifications for high-cardinality relationships. ## [](Ash.Resource.Change.CascadeDestroy.html#module-options)Options - `:relationship` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Required. The name of the relationship to work on - `:action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the destroy action to call on the related resource. Uses the primary destroy by default. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the read action to call on the related resource to find results to be destroyed - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Return notifications for all destroyed records? The default value is `false`. ## [](Ash.Resource.Change.CascadeDestroy.html#module-example)Example ``` change {Ash.Resource.Change.CascadeDestroy, relationship: :comments, action: :destroy} ``` or, equivalently using [`Ash.Resource.Change.Builtins.cascade_destroy/2`](Ash.Resource.Change.Builtins.html#cascade_destroy/2): ``` change cascade_destroy(:comments, action: :destroy) ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.CascadeUpdate (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/cascade_update.ex#L1 "View Source") Cascade a resource's update action to a related resource's update action. Adds an after-action hook that explicitly calls update on any records related via the named relationship. It will optimise for bulk updates where possible. Allows you to copy fields from the arguments or changes to the destination, this way you can cascade a bunch of changes downstream. #### Beware database constraints Think carefully before using this change with data layers which enforce referential integrity (ie PostgreSQL and SQLite) and you may need to defer constraints for the relationship in question. See also: 1. [`postgres.references.reference.deferrable` DSL](../ash_postgres/dsl-ashpostgres-datalayer.html#postgres-references-reference-deferrable) 2. [`sqlite.references.reference.deferrable` DSL](../ash_sqlite/dsl-ashsqlite-datalayer.html#sqlite-references-reference-deferrable) 3. [PostgreSQL's `SET CONSTRAINTS` documentation](https://www.postgresql.org/docs/current/sql-set-constraints.html) 4. [SQLite's `PRAGMA defer_foreign_keys` documentation](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) #### Cascading notifications By default notifications are disabled for the related updates. This is to avoid potentially sending a **lot** of notifications for high-cardinality relationships. ## [](Ash.Resource.Change.CascadeUpdate.html#module-options)Options - `:relationship` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Required. The name of the relationship to work on - `:action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the update action to call on the related resource. Uses the primary update by default. - `:copy_inputs` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A list of fields to copy &amp; pass on to the downstream update. The source action cannot be atomic. The default value is `[]`. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The name of the read action to call on the related resource to find results to be updated - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Return notifications for all updated records? The default value is `false`. ## [](Ash.Resource.Change.CascadeUpdate.html#module-example)Example ``` change {Ash.Resource.Change.CascadeUpdate, relationship: :comments, action: :update_all, copy_inputs: [:name]} or, equivalently using `Ash.Resource.Change.Builtins.cascade_update/2`: change cascade_update(:comments, action: :update_all, copy_inputs: [:name]) ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L87 "View Source") The context for a change. This is passed into various callbacks for [`Ash.Resource.Change`](Ash.Resource.Change.html). # [](Ash.Resource.Change.Context.html#summary)Summary ## [Types](Ash.Resource.Change.Context.html#types) [t()](Ash.Resource.Change.Context.html#t:t/0) # [](Ash.Resource.Change.Context.html#types)Types [](Ash.Resource.Change.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L95) ``` @type t() :: %Ash.Resource.Change.Context{ actor: Ash.Resource.record() | nil, authorize?: boolean() | nil, bulk?: boolean(), tenant: term(), tracer: Ash.Tracer.t() | [Ash.Tracer.t()] | nil } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.GetAndLockForUpdate (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/get_and_lock_for_update.ex#L1 "View Source") Refetches the record being updated or destroyed, and locks it for update. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.GetAndLock (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/get_and_lock.ex#L1 "View Source") Refetches the record being updated or destroyed, and locks it with the given type. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L1 "View Source") The behaviour for an action-specific resource change. [`init/1`](Ash.Resource.Change.html#c:init/1) is defined automatically by `use Ash.Resource.Change`, but can be implemented if you want to validate/transform any options passed to the module. The main function is [`change/3`](Ash.Resource.Change.html#c:change/3). It takes the changeset, any options that were provided when this change was configured on a resource, and the context, which currently only has the actor. # [](Ash.Resource.Change.html#summary)Summary ## [Types](Ash.Resource.Change.html#types) [context()](Ash.Resource.Change.html#t:context/0) [ref()](Ash.Resource.Change.html#t:ref/0) [t()](Ash.Resource.Change.html#t:t/0) ## [Callbacks](Ash.Resource.Change.html#callbacks) [after\_batch(changesets\_and\_results, opts, context)](Ash.Resource.Change.html#c:after_batch/3) Runs on each batch result after it is dispatched to the data layer. [atomic(changeset, opts, context)](Ash.Resource.Change.html#c:atomic/3) [atomic?()](Ash.Resource.Change.html#c:atomic?/0) [batch\_callbacks?(changesets\_or\_query, opts, context)](Ash.Resource.Change.html#c:batch_callbacks?/3) Whether or not batch callbacks should be run (if they are defined). Defaults to `true`. [batch\_change(changesets, opts, context)](Ash.Resource.Change.html#c:batch_change/3) Replaces `change/3` for batch actions, allowing to optimize changes for bulk actions. [before\_batch(changesets, opts, context)](Ash.Resource.Change.html#c:before_batch/3) Runs on each batch before it is dispatched to the data layer. [change(changeset, opts, context)](Ash.Resource.Change.html#c:change/3) [has\_after\_batch?()](Ash.Resource.Change.html#c:has_after_batch?/0) [has\_batch\_change?()](Ash.Resource.Change.html#c:has_batch_change?/0) [has\_before\_batch?()](Ash.Resource.Change.html#c:has_before_batch?/0) [has\_change?()](Ash.Resource.Change.html#c:has_change?/0) [init(opts)](Ash.Resource.Change.html#c:init/1) # [](Ash.Resource.Change.html#types)Types [](Ash.Resource.Change.html#t:context/0) # context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L104) ``` @type context() :: Ash.Resource.Change.Context.t() ``` [](Ash.Resource.Change.html#t:ref/0) # ref() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L15) ``` @type ref() :: {module(), Keyword.t()} | module() ``` [](Ash.Resource.Change.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L14) ``` @type t() :: %Ash.Resource.Change{ always_atomic?: term(), change: term(), description: term(), on: term(), only_when_valid?: term(), where: term() } ``` # [](Ash.Resource.Change.html#callbacks)Callbacks [](Ash.Resource.Change.html#c:after_batch/3) # after\_batch(changesets\_and\_results, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L136) ``` @callback after_batch( changesets_and_results :: [{Ash.Changeset.t(), Ash.Resource.record()}], opts :: Keyword.t(), context :: Ash.Resource.Change.Context.t() ) :: :ok | Enumerable.t( {:ok, Ash.Resource.record()} | {:error, Ash.Error.t()} | Ash.Notifier.Notification.t() ) ``` Runs on each batch result after it is dispatched to the data layer. [](Ash.Resource.Change.html#c:atomic/3) # atomic(changeset, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L158) ``` @callback atomic( changeset :: Ash.Changeset.t(), opts :: Keyword.t(), context :: Ash.Resource.Change.Context.t() ) :: {:ok, Ash.Changeset.t()} | {:atomic, %{optional(atom()) => Ash.Expr.t() | {:atomic, Ash.Expr.t()}}} | {:atomic, Ash.Changeset.t(), %{optional(atom()) => Ash.Expr.t()}} | {:atomic, Ash.Changeset.t(), %{optional(atom()) => Ash.Expr.t()}, [ {:atomic, involved_fields :: [atom()] | :*, condition_expr :: Ash.Expr.t(), error_expr :: Ash.Expr.t()} ]} | {:not_atomic, String.t()} | :ok | {:error, term()} ``` [](Ash.Resource.Change.html#c:atomic?/0) # atomic?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L171) ``` @callback atomic?() :: boolean() ``` [](Ash.Resource.Change.html#c:batch_callbacks?/3) # batch\_callbacks?(changesets\_or\_query, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L151) ``` @callback batch_callbacks?( changesets_or_query :: [Ash.Changeset.t()] | Ash.Query.t(), opts :: Keyword.t(), context :: Ash.Resource.Change.Context.t() ) :: boolean() ``` Whether or not batch callbacks should be run (if they are defined). Defaults to `true`. [](Ash.Resource.Change.html#c:batch_change/3) # batch\_change(changesets, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L116) ``` @callback batch_change( changesets :: [Ash.Changeset.t()], opts :: Keyword.t(), context :: Ash.Resource.Change.Context.t() ) :: Enumerable.t(Ash.Changeset.t()) ``` Replaces `change/3` for batch actions, allowing to optimize changes for bulk actions. You can define only `batch_change/3`, and it will be used for both single and batch actions. It cannot, however, be used in place of the `atomic/3` callback. [](Ash.Resource.Change.html#c:before_batch/3) # before\_batch(changesets, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L126) ``` @callback before_batch( changesets :: [Ash.Changeset.t()], opts :: Keyword.t(), context :: Ash.Resource.Change.Context.t() ) :: Enumerable.t(Ash.Changeset.t() | Ash.Notifier.Notification.t()) ``` Runs on each batch before it is dispatched to the data layer. [](Ash.Resource.Change.html#c:change/3) # change(changeset, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L107) ``` @callback change( changeset :: Ash.Changeset.t(), opts :: Keyword.t(), context :: Ash.Resource.Change.Context.t() ) :: Ash.Changeset.t() ``` [](Ash.Resource.Change.html#c:has_after_batch?/0) # has\_after\_batch?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L176) ``` @callback has_after_batch?() :: boolean() ``` [](Ash.Resource.Change.html#c:has_batch_change?/0) # has\_batch\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L175) ``` @callback has_batch_change?() :: boolean() ``` [](Ash.Resource.Change.html#c:has_before_batch?/0) # has\_before\_batch?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L177) ``` @callback has_before_batch?() :: boolean() ``` [](Ash.Resource.Change.html#c:has_change?/0) # has\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L173) ``` @callback has_change?() :: boolean() ``` [](Ash.Resource.Change.html#c:init/1) # init(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/change.ex#L106) ``` @callback init(opts :: Keyword.t()) :: {:ok, Keyword.t()} | {:error, term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.Increment (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/increment.ex#L1 "View Source") Increments an attribute's value by the amount specified, which defaults to 1. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Change.OptimisticLock (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/change/optimistic_lock.ex#L1 "View Source") Apply an "optimistic lock" on a record being updated or destroyed. ## [](Ash.Resource.Change.OptimisticLock.html#module-what-is-optimistic-locking)What is Optimistic Locking? Optimistic Locking is the process of only allowing an update to occur if the version of a record that you have in memory is the same as the version in the database. Otherwise, an error is returned. On success, it increments the version while performing the action. Optimistic locking may used for two primary purposes: ### [](Ash.Resource.Change.OptimisticLock.html#module-user-experience)User Experience For example, if a user is editing a form that contains `State` and `County` fields, and they change the `County`, while another user has used the form to change the `State`, you could end up with a mismatch between `State` and `County`. With optimistic locking, the user will instead get an error message that the record has been changed since they last looked. ### [](Ash.Resource.Change.OptimisticLock.html#module-concurrency-safety)Concurrency Safety Optimistic locking can make actions safe to run concurrently even if they can't be performed in a single query (atomically), by returning an error if the resource in the data layer does not have the same version as the one being edited. This tells the user that they need to reload and try again. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Dsl.Filter (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/dsl.ex#L2 "View Source") Introspection target for a filter for read actions and relationships [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L1 "View Source") A resource is a static definition of an entity in your system. [Resource DSL documentation](dsl-ash-resource.html) ### [](Ash.Resource.html#module-options)Options - `:simple_notifiers` (list of module that adopts [`Ash.Notifier`](Ash.Notifier.html)) - Notifiers with no DSL. - `:validate_domain_inclusion?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to validate that this resource is included in a domain. The default value is `true`. - `:domain` (module that adopts [`Ash.Domain`](Ash.Domain.html)) - The domain to use when interacting with this resource. Also sets defaults for various options that ask for a domain. - `:embed_nil_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to include keys with `nil` values in an embedded representation. Has no effect unless resource is an embedded resource. The default value is `true`. - `:extensions` (list of module that adopts [`Spark.Dsl.Extension`](../spark/2.2.40/Spark.Dsl.Extension.html)) - A list of DSL extensions to add to the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html) - `:data_layer` (module that adopts [`Ash.DataLayer`](Ash.DataLayer.html)) - data\_layer extensions to add to the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html) The default value is [`Ash.DataLayer.Simple`](Ash.DataLayer.Simple.html). - `:authorizers` (one or a list of module that adopts [`Ash.Authorizer`](Ash.Authorizer.html)) - authorizers extensions to add to the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html) The default value is `[]`. - `:notifiers` (one or a list of module that adopts [`Ash.Notifier`](Ash.Notifier.html)) - notifiers extensions to add to the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html) The default value is `[]`. - `:otp_app` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The otp\_app to use for any application configurable options - `:fragments` (list of [`module/0`](../elixir/typespecs.html#built-in-types)) - Fragments to include in the [`Spark.Dsl`](../spark/2.2.40/Spark.Dsl.html). See the fragments guide for more. # [](Ash.Resource.html#summary)Summary ## [Types](Ash.Resource.html#types) [record()](Ash.Resource.html#t:record/0) [t()](Ash.Resource.html#t:t/0) ## [Functions](Ash.Resource.html#functions) [foo()](Ash.Resource.html#foo/0) [get\_metadata(record, key\_or\_path)](Ash.Resource.html#get_metadata/2) [loaded?(data, path, opts \\\\ \[\])](Ash.Resource.html#loaded?/3) Returns true if the load or path to load has been loaded [put\_metadata(record, key, term)](Ash.Resource.html#put_metadata/3) [selected?(record, field, opts \\\\ \[\])](Ash.Resource.html#selected?/3) Returns true if the given field has been selected on a record [set\_metadata(record, map)](Ash.Resource.html#set_metadata/2) [unload(page, path)](Ash.Resource.html#unload/2) Sets a loaded key or path to a key back to its original unloaded stated [unload\_many(data, paths)](Ash.Resource.html#unload_many/2) Sets a list of loaded key or paths to a key back to their original unloaded stated # [](Ash.Resource.html#types)Types [](Ash.Resource.html#t:record/0) # record() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L15) ``` @type record() :: struct() ``` [](Ash.Resource.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L14) ``` @type t() :: module() ``` # [](Ash.Resource.html#functions)Functions [](Ash.Resource.html#foo/0) # foo() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L8) [](Ash.Resource.html#get_metadata/2) # get\_metadata(record, key\_or\_path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L579) ``` @spec get_metadata(record(), atom() | [atom()]) :: term() ``` [](Ash.Resource.html#loaded?/3) # loaded?(data, path, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L379) ``` @spec loaded?( nil | [record()] | record() | Ash.Page.page(), atom() | Ash.Query.Calculation.t() | Ash.Query.Aggregate.t() | [atom()], opts :: Keyword.t() ) :: boolean() ``` Returns true if the load or path to load has been loaded ## [](Ash.Resource.html#loaded?/3-options)Options - `lists`: set to `:any` to have this return true if any record in a list that appears has the value loaded. Default is `:all`. - `unknown`: set to `true` to have unknown paths (like nil values or non-resources) return true. Defaults to `false` - `strict?`: set to `true` to return false if a calculation with arguments is being checked [](Ash.Resource.html#put_metadata/3) # put\_metadata(record, key, term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L319) ``` @spec put_metadata(record(), atom(), term()) :: record() ``` [](Ash.Resource.html#selected?/3) # selected?(record, field, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L592) Returns true if the given field has been selected on a record ## [](Ash.Resource.html#selected?/3-options)Options - `forbidden_means_selected?`: set to `true` to return `true` if the field is marked as forbidden [](Ash.Resource.html#set_metadata/2) # set\_metadata(record, map) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L307) ``` @spec set_metadata(record(), map()) :: record() ``` [](Ash.Resource.html#unload/2) # unload(page, path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L339) ``` @spec unload( nil | [record()] | record() | Ash.Page.page(), atom() | [atom()] ) :: nil | [record()] | record() | Ash.Page.page() ``` Sets a loaded key or path to a key back to its original unloaded stated [](Ash.Resource.html#unload_many/2) # unload\_many(data, paths) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource.ex#L329) ``` @spec unload_many( nil | [record()] | record() | Ash.Page.page(), [atom()] | [[atom()]] ) :: nil | [record()] | record() | Ash.Page.page() ``` Sets a list of loaded key or paths to a key back to their original unloaded stated [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Identity (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/identity.ex#L1 "View Source") Represents a unique constraint on a resource Data layers should (and all built in ones do), discount `nil` or `null` (in the case of postgres) values when determining if a unique constraint matches. This often means that you should prefer to use identities with non-nullable columns. Eventually, features could be added to support including `nil` or `null` values, but they would need to include a corresponding feature for data layers. # [](Ash.Resource.Identity.html#summary)Summary ## [Types](Ash.Resource.Identity.html#types) [t()](Ash.Resource.Identity.html#t:t/0) ## [Functions](Ash.Resource.Identity.html#functions) [schema()](Ash.Resource.Identity.html#schema/0) # [](Ash.Resource.Identity.html#types)Types [](Ash.Resource.Identity.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/identity.ex#L88) ``` @type t() :: %Ash.Resource.Identity{ all_tenants?: boolean(), description: String.t() | nil, eager_check?: term(), eager_check_with: term(), keys: [atom()], message: term(), name: atom(), nils_distinct?: boolean(), pre_check?: term(), pre_check_with: term(), where: nil | Ash.Expr.t() } ``` # [](Ash.Resource.Identity.html#functions)Functions [](Ash.Resource.Identity.html#schema/0) # schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/identity.ex#L86) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Igniter (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L2 "View Source") Codemods for working with Ash.Resource modules ## [](Ash.Resource.Igniter.html#module-important-details)Important Details This interrogates *the source code* of a resource, not its ultimate compiled state. What this means, is that things like `defines_attribute` will not return `true` if the attribute is added by an extension. Only if it appears literally in the source code of the resource or one of its [`Spark.Dsl.Fragment`](../spark/2.2.40/Spark.Dsl.Fragment.html)s. # [](Ash.Resource.Igniter.html#summary)Summary ## [Functions](Ash.Resource.Igniter.html#functions) [add\_action(igniter, resource, action)](Ash.Resource.Igniter.html#add_action/3) Adds the given code block to the resource's `actions` block [add\_attribute(igniter, resource, attribute)](Ash.Resource.Igniter.html#add_attribute/3) Adds the given code block to the resource's `attributes` block [add\_block(igniter, resource, block, chunk)](Ash.Resource.Igniter.html#add_block/4) Adds the given code block to the block of the resource specified [add\_bypass(igniter, resource, condition, body)](Ash.Resource.Igniter.html#add_bypass/4) Adds a bypass to the top of the resource's `policies` block [add\_identity(igniter, resource, identity)](Ash.Resource.Igniter.html#add_identity/3) Adds the given code block to the resource's `identities` block [add\_new\_action(igniter, resource, name, action)](Ash.Resource.Igniter.html#add_new_action/4) Adds an action if it doesn't already exist [add\_new\_attribute(igniter, resource, name, attribute)](Ash.Resource.Igniter.html#add_new_attribute/4) Adds the given code block to the resource's `attributes` block if there is no existing attribute with the given name [add\_new\_identity(igniter, resource, name, identity)](Ash.Resource.Igniter.html#add_new_identity/4) Adds the given code block to the resource's `identities` block if there is no existing identity with the given name [add\_new\_relationship(igniter, resource, name, relationship)](Ash.Resource.Igniter.html#add_new_relationship/4) Adds the given code block to the resource's `relationships` block [add\_policy(igniter, resource, condition, body)](Ash.Resource.Igniter.html#add_policy/4) Adds a policy to the bottom of the resource's `policies` block [add\_relationship(igniter, resource, relationship)](Ash.Resource.Igniter.html#add_relationship/3) Adds the given code block to the resource's `relationships` block [add\_resource\_configuration(igniter, resource, resource\_configuration)](Ash.Resource.Igniter.html#add_resource_configuration/3) Adds the given code block to the resource's `resource` block [defines\_action(igniter, resource, name)](Ash.Resource.Igniter.html#defines_action/3) Returns true if the given resource defines an action with the provided name [defines\_attribute(igniter, resource, name)](Ash.Resource.Igniter.html#defines_attribute/3) Returns true if the given resource defines an attribute with the provided name [defines\_identity(igniter, resource, name)](Ash.Resource.Igniter.html#defines_identity/3) Returns true if the given resource defines an identity with the provided name [defines\_relationship(igniter, resource, name)](Ash.Resource.Igniter.html#defines_relationship/3) Returns true if the given resource defines a relationship with the provided name [domain(igniter, resource)](Ash.Resource.Igniter.html#domain/2) Gets the domain from the given resource module [ensure\_primary\_action(igniter, resource, type)](Ash.Resource.Igniter.html#ensure_primary_action/3) [ensure\_timestamps(igniter, resource)](Ash.Resource.Igniter.html#ensure_timestamps/2) Ensures that created\_at and updated\_at timestamps exist on the resource [has\_action\_with\_primary(igniter, resource, type)](Ash.Resource.Igniter.html#has_action_with_primary/3) [list\_resources(igniter)](Ash.Resource.Igniter.html#list_resources/1) List all resource modules found in the project [resource\_mods(igniter)](Ash.Resource.Igniter.html#resource_mods/1) # [](Ash.Resource.Igniter.html#functions)Functions [](Ash.Resource.Igniter.html#add_action/3) # add\_action(igniter, resource, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L372) Adds the given code block to the resource's `actions` block [](Ash.Resource.Igniter.html#add_attribute/3) # add\_attribute(igniter, resource, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L356) Adds the given code block to the resource's `attributes` block [](Ash.Resource.Igniter.html#add_block/4) # add\_block(igniter, resource, block, chunk) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L61) Adds the given code block to the block of the resource specified [](Ash.Resource.Igniter.html#add_bypass/4) # add\_bypass(igniter, resource, condition, body) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L85) Adds a bypass to the top of the resource's `policies` block [](Ash.Resource.Igniter.html#add_identity/3) # add\_identity(igniter, resource, identity) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L351) Adds the given code block to the resource's `identities` block [](Ash.Resource.Igniter.html#add_new_action/4) # add\_new\_action(igniter, resource, name, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L361) Adds an action if it doesn't already exist [](Ash.Resource.Igniter.html#add_new_attribute/4) # add\_new\_attribute(igniter, resource, name, attribute) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L329) Adds the given code block to the resource's `attributes` block if there is no existing attribute with the given name [](Ash.Resource.Igniter.html#add_new_identity/4) # add\_new\_identity(igniter, resource, name, identity) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L340) Adds the given code block to the resource's `identities` block if there is no existing identity with the given name [](Ash.Resource.Igniter.html#add_new_relationship/4) # add\_new\_relationship(igniter, resource, name, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L377) Adds the given code block to the resource's `relationships` block [](Ash.Resource.Igniter.html#add_policy/4) # add\_policy(igniter, resource, condition, body) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L123) Adds a policy to the bottom of the resource's `policies` block [](Ash.Resource.Igniter.html#add_relationship/3) # add\_relationship(igniter, resource, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L388) Adds the given code block to the resource's `relationships` block [](Ash.Resource.Igniter.html#add_resource_configuration/3) # add\_resource\_configuration(igniter, resource, resource\_configuration) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L393) Adds the given code block to the resource's `resource` block [](Ash.Resource.Igniter.html#defines_action/3) # defines\_action(igniter, resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L234) ``` @spec defines_action(Igniter.t(), Ash.Resource.t(), atom()) :: {Igniter.t(), true | false} ``` Returns true if the given resource defines an action with the provided name [](Ash.Resource.Igniter.html#defines_attribute/3) # defines\_attribute(igniter, resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L162) ``` @spec defines_attribute(Igniter.t(), Ash.Resource.t(), atom()) :: {Igniter.t(), true | false} ``` Returns true if the given resource defines an attribute with the provided name [](Ash.Resource.Igniter.html#defines_identity/3) # defines\_identity(igniter, resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L207) ``` @spec defines_identity(Igniter.t(), Ash.Resource.t(), atom()) :: {Igniter.t(), true | false} ``` Returns true if the given resource defines an identity with the provided name [](Ash.Resource.Igniter.html#defines_relationship/3) # defines\_relationship(igniter, resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L298) ``` @spec defines_relationship(Igniter.t(), Ash.Resource.t(), atom()) :: {Igniter.t(), true | false} ``` Returns true if the given resource defines a relationship with the provided name [](Ash.Resource.Igniter.html#domain/2) # domain(igniter, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L32) ``` @spec domain(Igniter.t(), Ash.Resource.t()) :: {:ok, Igniter.t(), Ash.Domain.t()} | {:error, Igniter.t()} ``` Gets the domain from the given resource module [](Ash.Resource.Igniter.html#ensure_primary_action/3) # ensure\_primary\_action(igniter, resource, type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L282) ``` @spec ensure_primary_action( Igniter.t(), Ash.Resource.t(), :create | :read | :update | :destroy ) :: Igniter.t() ``` [](Ash.Resource.Igniter.html#ensure_timestamps/2) # ensure\_timestamps(igniter, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L398) Ensures that created\_at and updated\_at timestamps exist on the resource [](Ash.Resource.Igniter.html#has_action_with_primary/3) # has\_action\_with\_primary(igniter, resource, type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L499) ``` @spec has_action_with_primary(Igniter.t(), Ash.Resource.t(), atom()) :: {Igniter.t(), true | false} ``` [](Ash.Resource.Igniter.html#list_resources/1) # list\_resources(igniter) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L15) List all resource modules found in the project [](Ash.Resource.Igniter.html#resource_mods/1) # resource\_mods(igniter) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/igniter.ex#L54) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Info (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L1 "View Source") Introspection for resources # [](Ash.Resource.Info.html#summary)Summary ## [Functions](Ash.Resource.Info.html#functions) [action(resource, name, type \\\\ nil)](Ash.Resource.Info.html#action/3) Returns the action with the matching name and type on the resource [action\_input?(resource, action, input)](Ash.Resource.Info.html#action_input?/3) Returns true or false if the input is accepted by the action, as an argument or an attribute [action\_inputs(resource, action)](Ash.Resource.Info.html#action_inputs/2) Returns the list of possible accepted keys by an action [action\_select(resource, action)](Ash.Resource.Info.html#action_select/2) Returns the list of attributes that must be selected for an action invocation [actions(resource)](Ash.Resource.Info.html#actions/1) Returns all actions of a resource [aggregate(resource, name)](Ash.Resource.Info.html#aggregate/2) Get an aggregate by name [aggregate\_type(resource, aggregate)](Ash.Resource.Info.html#aggregate_type/2) Gets the type of an aggregate for a given resource. [aggregates(resource)](Ash.Resource.Info.html#aggregates/1) Returns all aggregates of a resource [always\_selected\_attribute\_names(resource)](Ash.Resource.Info.html#always_selected_attribute_names/1) [attribute(resource, name)](Ash.Resource.Info.html#attribute/2) Get an attribute name from the resource [attribute\_names(resource)](Ash.Resource.Info.html#attribute_names/1) [attributes(resource)](Ash.Resource.Info.html#attributes/1) Returns all attributes of a resource [attributes\_to\_require(resource)](Ash.Resource.Info.html#attributes_to_require/1) [attributes\_to\_require(resource, action\_name)](Ash.Resource.Info.html#attributes_to_require/2) [authorizers(resource)](Ash.Resource.Info.html#authorizers/1) A list of authorizers to be used when accessing [base\_filter(resource)](Ash.Resource.Info.html#base_filter/1) The base filter of the resource [calculation(resource, name)](Ash.Resource.Info.html#calculation/2) Get a calculation by name [calculation\_interface(resource, name)](Ash.Resource.Info.html#calculation_interface/2) Get an calculation interface by name from the resource [calculation\_interfaces(resource)](Ash.Resource.Info.html#calculation_interfaces/1) The list of code interface calculation definitions. [calculations(resource)](Ash.Resource.Info.html#calculations/1) Returns all calculations of a resource [changes(resource)](Ash.Resource.Info.html#changes/1) A list of all changes for the resource [changes(resource, type)](Ash.Resource.Info.html#changes/2) A list of all changes for the resource for a given action type [code\_interface\_domain(resource)](Ash.Resource.Info.html#code_interface_domain/1) The domain to define the interface for, when defining it in the resource [data\_layer(resource)](Ash.Resource.Info.html#data_layer/1) The data layer of the resource, or nil if it does not have one [default\_actions(resource)](Ash.Resource.Info.html#default_actions/1) Returns the configured default actions [default\_context(resource)](Ash.Resource.Info.html#default_context/1) The default context of the resource [define\_interface?(resource)](Ash.Resource.Info.html#define_interface?/1) Whether or not to define the interface on the resource [description(resource)](Ash.Resource.Info.html#description/1) The description of the resource [domain(resource)](Ash.Resource.Info.html#domain/1) Returns the statically configured domain for the resource. [embedded?(resource)](Ash.Resource.Info.html#embedded?/1) Whether or not the resource is an embedded resource [field(resource, name)](Ash.Resource.Info.html#field/2) Get a field from a resource by name [fields(resource, types \\\\ \[:attributes, :aggregates, :calculations, :relationships\])](Ash.Resource.Info.html#fields/2) Returns all attributes, aggregates, calculations and relationships of a resource [identities(resource)](Ash.Resource.Info.html#identities/1) A list of identities for the resource [identity(resource, name)](Ash.Resource.Info.html#identity/2) Get an identity by name from the resource [interface(resource, name)](Ash.Resource.Info.html#interface/2) Get an interface by name from the resource [interfaces(resource)](Ash.Resource.Info.html#interfaces/1) The list of code interface definitions. [lazy\_matching\_default\_attributes(resource, atom)](Ash.Resource.Info.html#lazy_matching_default_attributes/2) Returns all attributes of a resource with lazy matching defaults [lazy\_non\_matching\_default\_attributes(resource, atom)](Ash.Resource.Info.html#lazy_non_matching_default_attributes/2) Returns all attributes of a resource with lazy non-matching-defaults [multitenancy\_attribute(resource)](Ash.Resource.Info.html#multitenancy_attribute/1) The multitenancy attribute for a resource [multitenancy\_global?(resource)](Ash.Resource.Info.html#multitenancy_global?/1) The MFA to parse the tenant from the attribute [multitenancy\_parse\_attribute(resource)](Ash.Resource.Info.html#multitenancy_parse_attribute/1) The function to parse the tenant from the attribute [multitenancy\_strategy(resource)](Ash.Resource.Info.html#multitenancy_strategy/1) The multitenancy strategy for a resource [multitenancy\_template(resource)](Ash.Resource.Info.html#multitenancy_template/1) The template for creating the tenant name [notifiers(resource)](Ash.Resource.Info.html#notifiers/1) A list of notifiers to be used when accessing [plural\_name(resource)](Ash.Resource.Info.html#plural_name/1) The plural\_name of the resource [preparations(resource)](Ash.Resource.Info.html#preparations/1) [primary\_action(resource, type)](Ash.Resource.Info.html#primary_action/2) Returns the primary action of a given type [primary\_action!(resource, type)](Ash.Resource.Info.html#primary_action!/2) Returns the primary action of the given type [primary\_key(resource)](Ash.Resource.Info.html#primary_key/1) A list of field names corresponding to the primary key [primary\_key\_simple\_equality?(resource)](Ash.Resource.Info.html#primary_key_simple_equality?/1) Whether or not all primary key attributes can be compared with simple\_equality [public\_aggregate(resource, name)](Ash.Resource.Info.html#public_aggregate/2) Get an aggregate by name [public\_aggregates(resource)](Ash.Resource.Info.html#public_aggregates/1) Returns all public aggregates of a resource [public\_attribute(resource, name)](Ash.Resource.Info.html#public_attribute/2) Get a public attribute name from the resource [public\_attributes(resource)](Ash.Resource.Info.html#public_attributes/1) Returns all public attributes of a resource [public\_calculation(resource, name)](Ash.Resource.Info.html#public_calculation/2) Get a public calculation by name [public\_calculations(resource)](Ash.Resource.Info.html#public_calculations/1) Returns all public calculations of a resource [public\_field(resource, name)](Ash.Resource.Info.html#public_field/2) Get a public field from a resource by name [public\_fields(resource)](Ash.Resource.Info.html#public_fields/1) Returns all public attributes, aggregates, calculations and relationships of a resource [public\_relationship(resource, relationship\_name)](Ash.Resource.Info.html#public_relationship/2) Get a public relationship by name or path [public\_relationships(resource)](Ash.Resource.Info.html#public_relationships/1) Returns all public relationships of a resource [related(resource, relationship)](Ash.Resource.Info.html#related/2) [relationship(resource, relationship\_name)](Ash.Resource.Info.html#relationship/2) Get a relationship by name or path [relationships(resource)](Ash.Resource.Info.html#relationships/1) Returns all relationships of a resource [required\_belongs\_to\_relationships(resource)](Ash.Resource.Info.html#required_belongs_to_relationships/1) The required belongs\_to relationships [resource?(module)](Ash.Resource.Info.html#resource?/1) Whether or not a given module is a resource module [reverse\_relationship(resource, path, acc \\\\ \[\])](Ash.Resource.Info.html#reverse_relationship/3) Retrieves a relationship path from the resource related by path, to the provided resource. [selected\_by\_default\_attribute\_names(resource)](Ash.Resource.Info.html#selected_by_default_attribute_names/1) [short\_name(resource)](Ash.Resource.Info.html#short_name/1) The short\_name of the resource [simple\_notifiers(resource)](Ash.Resource.Info.html#simple_notifiers/1) A list of simple notifiers (require no DSL, used to avoid compile time dependencies) [sortable?(resource, name, opts \\\\ \[\])](Ash.Resource.Info.html#sortable?/3) Determine if a field is sortable by name [static\_default\_attributes(resource, atom)](Ash.Resource.Info.html#static_default_attributes/2) Returns all attributes of a resource with static defaults [trace\_name(resource)](Ash.Resource.Info.html#trace_name/1) The trace\_name of the resource [unique\_keys(resource)](Ash.Resource.Info.html#unique_keys/1) A list of unique keys and information for a resource [validations(resource)](Ash.Resource.Info.html#validations/1) A list of all validations for the resource [validations(resource, type)](Ash.Resource.Info.html#validations/2) A list of all validations for the resource for a given action type # [](Ash.Resource.Info.html#functions)Functions [](Ash.Resource.Info.html#action/3) # action(resource, name, type \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L600) ``` @spec action( Spark.Dsl.t() | Ash.Resource.t(), atom(), Ash.Resource.Actions.action_type() | nil ) :: Ash.Resource.Actions.action() | nil ``` Returns the action with the matching name and type on the resource [](Ash.Resource.Info.html#action_input?/3) # action\_input?(resource, action, input) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L630) ``` @spec action_input?(Ash.Resource.t(), action :: atom(), input :: atom() | String.t()) :: boolean() ``` Returns true or false if the input is accepted by the action, as an argument or an attribute [](Ash.Resource.Info.html#action_inputs/2) # action\_inputs(resource, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L642) ``` @spec action_inputs(Ash.Resource.t(), action :: atom()) :: MapSet.t() ``` Returns the list of possible accepted keys by an action [](Ash.Resource.Info.html#action_select/2) # action\_select(resource, action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L649) ``` @spec action_select( Ash.Resource.t(), action :: atom() | Ash.Resource.Actions.action() ) :: [atom()] | nil ``` Returns the list of attributes that must be selected for an action invocation [](Ash.Resource.Info.html#actions/1) # actions(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L593) ``` @spec actions(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Actions.action()] ``` Returns all actions of a resource [](Ash.Resource.Info.html#aggregate/2) # aggregate(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L514) ``` @spec aggregate(Spark.Dsl.t() | Ash.Resource.t(), atom() | String.t()) :: Ash.Resource.Aggregate.t() | nil ``` Get an aggregate by name [](Ash.Resource.Info.html#aggregate_type/2) # aggregate\_type(resource, aggregate) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L475) ``` @spec aggregate_type( Spark.Dsl.t() | Ash.Resource.t(), Ash.Resource.Aggregate.t() | atom() ) :: {:ok, Ash.Type.t()} | {:error, String.t()} ``` Gets the type of an aggregate for a given resource. [](Ash.Resource.Info.html#aggregates/1) # aggregates(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L507) ``` @spec aggregates(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Aggregate.t()] ``` Returns all aggregates of a resource [](Ash.Resource.Info.html#always_selected_attribute_names/1) # always\_selected\_attribute\_names(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L789) ``` @spec always_selected_attribute_names(Spark.Dsl.t() | Ash.Resource.t()) :: MapSet.t() ``` [](Ash.Resource.Info.html#attribute/2) # attribute(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L743) ``` @spec attribute(Spark.Dsl.t() | Ash.Resource.t(), String.t() | atom()) :: Ash.Resource.Attribute.t() | nil ``` Get an attribute name from the resource [](Ash.Resource.Info.html#attribute_names/1) # attribute\_names(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L664) ``` @spec attribute_names(Spark.Dsl.t() | Ash.Resource.t()) :: MapSet.t() ``` [](Ash.Resource.Info.html#attributes/1) # attributes(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L659) ``` @spec attributes(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Attribute.t()] ``` Returns all attributes of a resource [](Ash.Resource.Info.html#attributes_to_require/1) # attributes\_to\_require(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L355) [](Ash.Resource.Info.html#attributes_to_require/2) # attributes\_to\_require(resource, action\_name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L359) [](Ash.Resource.Info.html#authorizers/1) # authorizers(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L219) ``` @spec authorizers(Spark.Dsl.t() | Ash.Resource.t()) :: [module()] ``` A list of authorizers to be used when accessing [](Ash.Resource.Info.html#base_filter/1) # base\_filter(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L191) ``` @spec base_filter(Spark.Dsl.t() | Ash.Resource.t()) :: term() ``` The base filter of the resource [](Ash.Resource.Info.html#calculation/2) # calculation(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L432) ``` @spec calculation(Spark.Dsl.t() | Ash.Resource.t(), atom() | String.t()) :: Ash.Resource.Calculation.t() | nil ``` Get a calculation by name [](Ash.Resource.Info.html#calculation_interface/2) # calculation\_interface(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L107) ``` @spec calculation_interface(Spark.Dsl.t() | Ash.Resource.t(), atom()) :: Ash.Resource.CalculationInterface.t() | nil ``` Get an calculation interface by name from the resource [](Ash.Resource.Info.html#calculation_interfaces/1) # calculation\_interfaces(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L92) ``` @spec calculation_interfaces(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.CalculationInterface.t() ] ``` The list of code interface calculation definitions. [](Ash.Resource.Info.html#calculations/1) # calculations(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L425) ``` @spec calculations(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Calculation.t()] ``` Returns all calculations of a resource [](Ash.Resource.Info.html#changes/1) # changes(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L262) ``` @spec changes(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.Validation.t() | Ash.Resource.Change.t() ] ``` A list of all changes for the resource [](Ash.Resource.Info.html#changes/2) # changes(resource, type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L252) ``` @spec changes(Spark.Dsl.t() | Ash.Resource.t(), :create | :update | :destroy) :: [ Ash.Resource.Validation.t() | Ash.Resource.Change.t() ] ``` A list of all changes for the resource for a given action type [](Ash.Resource.Info.html#code_interface_domain/1) # code\_interface\_domain(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L117) ``` @spec code_interface_domain(Spark.Dsl.t() | Ash.Resource.t()) :: atom() | nil ``` The domain to define the interface for, when defining it in the resource [](Ash.Resource.Info.html#data_layer/1) # data\_layer(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L908) ``` @spec data_layer(Ash.Resource.t()) :: Ash.DataLayer.t() | nil ``` The data layer of the resource, or nil if it does not have one [](Ash.Resource.Info.html#default_actions/1) # default\_actions(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L574) ``` @spec default_actions(Spark.Dsl.t() | Ash.Resource.t()) :: [ :create | :read | :update | :destroy ] ``` Returns the configured default actions [](Ash.Resource.Info.html#default_context/1) # default\_context(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L199) ``` @spec default_context(Spark.Dsl.t() | Ash.Resource.t()) :: term() ``` The default context of the resource [](Ash.Resource.Info.html#define_interface?/1) # define\_interface?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L125) ``` @spec define_interface?(Spark.Dsl.t() | Ash.Resource.t()) :: boolean() ``` Whether or not to define the interface on the resource [](Ash.Resource.Info.html#description/1) # description(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L141) ``` @spec description(Spark.Dsl.t() | Ash.Resource.t()) :: String.t() | nil ``` The description of the resource [](Ash.Resource.Info.html#domain/1) # domain(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L9) Returns the statically configured domain for the resource. [](Ash.Resource.Info.html#embedded?/1) # embedded?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L133) ``` @spec embedded?(Spark.Dsl.t() | Ash.Resource.t()) :: boolean() ``` Whether or not the resource is an embedded resource [](Ash.Resource.Info.html#field/2) # field(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L819) ``` @spec field(Spark.Dsl.t() | Ash.Resource.t(), String.t() | atom()) :: Ash.Resource.Attribute.t() | Ash.Resource.Aggregate.t() | Ash.Resource.Calculation.t() | Ash.Resource.Relationships.relationship() | nil ``` Get a field from a resource by name [](Ash.Resource.Info.html#fields/2) # fields(resource, types \\\\ \[:attributes, :aggregates, :calculations, :relationships]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L808) ``` @spec fields( Spark.Dsl.t() | Ash.Resource.t(), types :: [:attributes | :aggregates | :calculations | :relationships] ) :: [ Ash.Resource.Attribute.t() | Ash.Resource.Aggregate.t() | Ash.Resource.Calculation.t() | Ash.Resource.Relationships.relationship() ] ``` Returns all attributes, aggregates, calculations and relationships of a resource [](Ash.Resource.Info.html#identities/1) # identities(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L205) ``` @spec identities(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Identity.t()] ``` A list of identities for the resource [](Ash.Resource.Info.html#identity/2) # identity(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L211) ``` @spec identity(Spark.Dsl.t() | Ash.Resource.t(), atom()) :: Ash.Resource.Identity.t() | nil ``` Get an identity by name from the resource [](Ash.Resource.Info.html#interface/2) # interface(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L80) ``` @spec interface(Spark.Dsl.t() | Ash.Resource.t(), atom()) :: Ash.Resource.Interface.t() | nil ``` Get an interface by name from the resource [](Ash.Resource.Info.html#interfaces/1) # interfaces(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L66) ``` @spec interfaces(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Interface.t()] ``` The list of code interface definitions. [](Ash.Resource.Info.html#lazy_matching_default_attributes/2) # lazy\_matching\_default\_attributes(resource, atom) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L721) ``` @spec lazy_matching_default_attributes( Spark.Dsl.t() | Ash.Resource.t(), type :: :create | :update ) :: [Ash.Resource.Attribute.t()] ``` Returns all attributes of a resource with lazy matching defaults [](Ash.Resource.Info.html#lazy_non_matching_default_attributes/2) # lazy\_non\_matching\_default\_attributes(resource, atom) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L673) ``` @spec lazy_non_matching_default_attributes( Spark.Dsl.t() | Ash.Resource.t(), type :: :create | :update ) :: [Ash.Resource.Attribute.t()] ``` Returns all attributes of a resource with lazy non-matching-defaults [](Ash.Resource.Info.html#multitenancy_attribute/1) # multitenancy\_attribute(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L393) ``` @spec multitenancy_attribute(Spark.Dsl.t() | Ash.Resource.t()) :: atom() | nil ``` The multitenancy attribute for a resource [](Ash.Resource.Info.html#multitenancy_global?/1) # multitenancy\_global?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L413) ``` @spec multitenancy_global?(Spark.Dsl.t() | Ash.Resource.t()) :: atom() | nil ``` The MFA to parse the tenant from the attribute [](Ash.Resource.Info.html#multitenancy_parse_attribute/1) # multitenancy\_parse\_attribute(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L399) ``` @spec multitenancy_parse_attribute(Spark.Dsl.t() | Ash.Resource.t()) :: {atom(), atom(), [any()]} ``` The function to parse the tenant from the attribute [](Ash.Resource.Info.html#multitenancy_strategy/1) # multitenancy\_strategy(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L387) ``` @spec multitenancy_strategy(Spark.Dsl.t() | Ash.Resource.t()) :: :context | :attribute | nil ``` The multitenancy strategy for a resource [](Ash.Resource.Info.html#multitenancy_template/1) # multitenancy\_template(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L419) ``` @spec multitenancy_template(Spark.Dsl.t() | Ash.Resource.t()) :: atom() | nil ``` The template for creating the tenant name [](Ash.Resource.Info.html#notifiers/1) # notifiers(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L225) ``` @spec notifiers(Spark.Dsl.t() | Ash.Resource.t()) :: [module()] ``` A list of notifiers to be used when accessing [](Ash.Resource.Info.html#plural_name/1) # plural\_name(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L183) The plural\_name of the resource [](Ash.Resource.Info.html#preparations/1) # preparations(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L267) ``` @spec preparations(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Preparation.t()] ``` [](Ash.Resource.Info.html#primary_action/2) # primary\_action(resource, type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L565) ``` @spec primary_action( Spark.Dsl.t() | Ash.Resource.t(), Ash.Resource.Actions.action_type() ) :: Ash.Resource.Actions.action() | nil ``` Returns the primary action of a given type [](Ash.Resource.Info.html#primary_action!/2) # primary\_action!(resource, type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L552) ``` @spec primary_action!( Spark.Dsl.t() | Ash.Resource.t(), Ash.Resource.Actions.action_type() ) :: Ash.Resource.Actions.action() | no_return() ``` Returns the primary action of the given type [](Ash.Resource.Info.html#primary_key/1) # primary\_key(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L281) ``` @spec primary_key(Spark.Dsl.t() | Ash.Resource.t()) :: [atom()] ``` A list of field names corresponding to the primary key [](Ash.Resource.Info.html#primary_key_simple_equality?/1) # primary\_key\_simple\_equality?(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L294) ``` @spec primary_key_simple_equality?(Spark.Dsl.t() | Ash.Resource.t()) :: boolean() ``` Whether or not all primary key attributes can be compared with simple\_equality [](Ash.Resource.Info.html#public_aggregate/2) # public\_aggregate(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L537) ``` @spec public_aggregate(Spark.Dsl.t() | Ash.Resource.t(), atom() | String.t()) :: Ash.Resource.Aggregate.t() | nil ``` Get an aggregate by name [](Ash.Resource.Info.html#public_aggregates/1) # public\_aggregates(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L528) ``` @spec public_aggregates(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.Aggregate.t() ] ``` Returns all public aggregates of a resource [](Ash.Resource.Info.html#public_attribute/2) # public\_attribute(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L766) ``` @spec public_attribute(Spark.Dsl.t() | Ash.Resource.t(), String.t() | atom()) :: Ash.Resource.Attribute.t() | nil ``` Get a public attribute name from the resource [](Ash.Resource.Info.html#public_attributes/1) # public\_attributes(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L757) ``` @spec public_attributes(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.Attribute.t() ] ``` Returns all public attributes of a resource [](Ash.Resource.Info.html#public_calculation/2) # public\_calculation(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L458) ``` @spec public_calculation(Spark.Dsl.t() | Ash.Resource.t(), atom() | String.t()) :: Ash.Resource.Calculation.t() | nil ``` Get a public calculation by name [](Ash.Resource.Info.html#public_calculations/1) # public\_calculations(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L449) ``` @spec public_calculations(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.Calculation.t() ] ``` Returns all public calculations of a resource [](Ash.Resource.Info.html#public_field/2) # public\_field(resource, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L846) ``` @spec public_field(Spark.Dsl.t() | Ash.Resource.t(), String.t() | atom()) :: Ash.Resource.Attribute.t() | Ash.Resource.Aggregate.t() | Ash.Resource.Calculation.t() | Ash.Resource.Relationships.relationship() | nil ``` Get a public field from a resource by name [](Ash.Resource.Info.html#public_fields/1) # public\_fields(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L833) ``` @spec public_fields(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.Attribute.t() | Ash.Resource.Aggregate.t() | Ash.Resource.Calculation.t() | Ash.Resource.Relationships.relationship() ] ``` Returns all public attributes, aggregates, calculations and relationships of a resource [](Ash.Resource.Info.html#public_relationship/2) # public\_relationship(resource, relationship\_name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L364) Get a public relationship by name or path [](Ash.Resource.Info.html#public_relationships/1) # public\_relationships(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L340) ``` @spec public_relationships(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.Relationships.relationship() ] ``` Returns all public relationships of a resource [](Ash.Resource.Info.html#related/2) # related(resource, relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L775) ``` @spec related( Spark.Dsl.t() | Ash.Resource.t(), atom() | String.t() | [atom() | String.t()] ) :: Ash.Resource.t() | nil ``` [](Ash.Resource.Info.html#relationship/2) # relationship(resource, relationship\_name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L308) ``` @spec relationship( Spark.Dsl.t() | Ash.Resource.t(), atom() | String.t() | [atom() | String.t()] ) :: Ash.Resource.Relationships.relationship() | nil ``` Get a relationship by name or path [](Ash.Resource.Info.html#relationships/1) # relationships(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L301) ``` @spec relationships(Spark.Dsl.t() | Ash.Resource.t()) :: [ Ash.Resource.Relationships.relationship() ] ``` Returns all relationships of a resource [](Ash.Resource.Info.html#required_belongs_to_relationships/1) # required\_belongs\_to\_relationships(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L347) The required belongs\_to relationships [](Ash.Resource.Info.html#resource?/1) # resource?(module) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L273) ``` @spec resource?(module()) :: boolean() ``` Whether or not a given module is a resource module [](Ash.Resource.Info.html#reverse_relationship/3) # reverse\_relationship(resource, path, acc \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L16) Retrieves a relationship path from the resource related by path, to the provided resource. [](Ash.Resource.Info.html#selected_by_default_attribute_names/1) # selected\_by\_default\_attribute\_names(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L794) ``` @spec selected_by_default_attribute_names(Spark.Dsl.t() | Ash.Resource.t()) :: MapSet.t() ``` [](Ash.Resource.Info.html#short_name/1) # short\_name(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L166) ``` @spec short_name(Spark.Dsl.t() | Ash.Resource.t()) :: atom() | nil ``` The short\_name of the resource [](Ash.Resource.Info.html#simple_notifiers/1) # simple\_notifiers(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L149) ``` @spec simple_notifiers(Spark.Dsl.t() | Ash.Resource.t()) :: [module()] ``` A list of simple notifiers (require no DSL, used to avoid compile time dependencies) [](Ash.Resource.Info.html#sortable?/3) # sortable?(resource, name, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L859) ``` @spec sortable?(Spark.Dsl.t() | Ash.Resource.t(), String.t() | atom(), pagination_type: Ash.Page.type(), include_private?: boolean() ) :: boolean() ``` Determine if a field is sortable by name [](Ash.Resource.Info.html#static_default_attributes/2) # static\_default\_attributes(resource, atom) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L694) ``` @spec static_default_attributes( Spark.Dsl.t() | Ash.Resource.t(), type :: :create | :update ) :: [Ash.Resource.Attribute.t()] ``` Returns all attributes of a resource with static defaults [](Ash.Resource.Info.html#trace_name/1) # trace\_name(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L157) ``` @spec trace_name(Spark.Dsl.t() | Ash.Resource.t()) :: String.t() | nil ``` The trace\_name of the resource [](Ash.Resource.Info.html#unique_keys/1) # unique\_keys(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L288) ``` @spec unique_keys(Spark.Dsl.t() | Ash.Resource.t()) :: [ %{type: atom(), keys: [atom()], nils_distinct?: boolean()} ] ``` A list of unique keys and information for a resource [](Ash.Resource.Info.html#validations/1) # validations(resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L242) ``` @spec validations(Spark.Dsl.t() | Ash.Resource.t()) :: [Ash.Resource.Validation.t()] ``` A list of all validations for the resource [](Ash.Resource.Info.html#validations/2) # validations(resource, type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/info.ex#L233) ``` @spec validations(Spark.Dsl.t() | Ash.Resource.t(), :create | :update | :destroy) :: [ Ash.Resource.Validation.t() ] ``` A list of all validations for the resource for a given action type [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Interface (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L1 "View Source") Represents a function in a resource's code interface See the functions defined in this module for specifications of the options that each type of code interface function supports in its options list. # [](Ash.Resource.Interface.html#summary)Summary ## [Types](Ash.Resource.Interface.html#types) [t()](Ash.Resource.Interface.html#t:t/0) ## [Functions](Ash.Resource.Interface.html#functions) [calculate\_opts()](Ash.Resource.Interface.html#calculate_opts/0) Options supported by code interfaces for calculations [create\_opts()](Ash.Resource.Interface.html#create_opts/0) Options supported by code interfaces for create actions [destroy\_opts()](Ash.Resource.Interface.html#destroy_opts/0) Options supported by code interfaces for destroy actions [generic\_action\_opts()](Ash.Resource.Interface.html#generic_action_opts/0) Options supported by code interfaces for generic actions [get\_opts()](Ash.Resource.Interface.html#get_opts/0) Options supported by code interfaces for read actions with `get?` or `get_by` set. [read\_opts()](Ash.Resource.Interface.html#read_opts/0) Options supported by code interfaces for read actions [update\_opts()](Ash.Resource.Interface.html#update_opts/0) Options supported by code interfaces for update actions # [](Ash.Resource.Interface.html#types)Types [](Ash.Resource.Interface.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L20) ``` @type t() :: %Ash.Resource.Interface{ action: term(), args: term(), default_options: term(), get?: term(), get_by: term(), get_by_identity: term(), name: term(), not_found_error?: term(), require_reference?: term() } ``` # [](Ash.Resource.Interface.html#functions)Functions [](Ash.Resource.Interface.html#calculate_opts/0) # calculate\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L243) Options supported by code interfaces for calculations ## [](Ash.Resource.Interface.html#calculate_opts/0-options)Options - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The actor for handling [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates, supplied to calculation context. - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - The tenant, supplied to calculation context. - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not the request is being authorized, provided to calculation context. The default value is `true`. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer, provided to the calculation context. - `:data_layer?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Set to `true` to require that the value be computed within the data layer. Only works for calculations that define an expression. [](Ash.Resource.Interface.html#create_opts/0) # create\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L177) Options supported by code interfaces for create actions ## [](Ash.Resource.Interface.html#create_opts/0-options)Options - `:upsert?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If a conflict is found based on the primary key, the record is updated in the database (requires upsert support) The default value is `false`. - `:return_skipped_upsert?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, and a record was *not* upserted because its filter prevented the upsert, the original record (which was *not* upserted) will be returned. The default value is `false`. - `:upsert_identity` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The identity to use when detecting conflicts for `upsert?`, e.g. `upsert_identity: :full_name`. By default, the primary key is used. Has no effect if `upsert?: true` is not provided - `:upsert_fields` - The fields to upsert. If not set, the action's upsert\_fields is used, and if that is not set, then any fields not being set to defaults are written. - `:upsert_condition` ([`term/0`](../elixir/typespecs.html#built-in-types)) - An expression to check if the record should be updated when there's a conflict. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the changeset - `:changeset` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A changeset to seed the action with. - `:bulk_options` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - Options passed to `Ash.bulk_create`, if a list or stream of inputs is provided. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:after_action` (function of arity 2) - An after\_action hook to be added to each processed changeset - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The action to use when building the read query. - `:assume_casted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting The default value is `false`. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:authorize_query_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Uses `authorize_with` if not set. - `:authorize_changeset_with` - If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error. Uses `authorize_with` if not set. - `:authorize_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. The default value is `:filter`. - `:sorted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to sort results by their input position, in cases where `return_records?: true` was provided. The default value is `false`. - `:return_records?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts. The default value is `false`. - `:return_errors?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the errors that occur. Defaults to false to account for large inserts. The default value is `false`. - `:batch_size` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100. - `:return_stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned. Potential elements: `{:notification, notification}` - if `return_notifications?` is set to `true` `{:ok, record}` - if `return_records?` is set to `true` `{:error, error}` - an error that occurred. May be changeset or an invidual error. The default value is `false`. - `:return_nothing?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Mutes warnings about returning nothing. Only relevant if `return_stream?` is set to `true` and all other `return_*?` options are set to `false`. The default value is `false`. - `:stop_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. The default value is `false`. - `:notify?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to generate any notifications. If this is set to `true` then the data layer must return the results from each batch. This may be intensive for large bulk actions. Notifications will be automatically sent unless `return_notifications?` is set to `true`. The default value is `false`. - `:transaction` - Whether or not to wrap the entire execution in a transaction, each batch, or not at all. Keep in mind: `before_transaction` and `after_transaction` hooks attached to changesets will have to be run *inside* the transaction if you choose `transaction: :all`. The default value is `:batch`. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously The default value is `0`. [](Ash.Resource.Interface.html#destroy_opts/0) # destroy\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L221) Options supported by code interfaces for destroy actions ## [](Ash.Resource.Interface.html#destroy_opts/0-options)Options - `:return_destroyed?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the destroyed record is included in the return result, e.g `{:ok, destroyed}` or `{:ok, destroyed, notifications}` The default value is `false`. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the changeset - `:bulk_options` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - Options passed to `Ash.bulk_create`, if a query, list, or stream of inputs is provided. - `:stream_batch_size` ([`integer/0`](../elixir/typespecs.html#basic-types)) - Batch size to use if provided a query and the query must be streamed - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records if the `:stream` strategy is chosen. See the [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. The default value is `:keyset`. - `:authorize_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If a query is given, determines whether or not authorization is run on that query. The default value is `true`. - `:strategy` - The strategy or strategies to enable. :stream is used in all cases if the data layer does not support atomics. The default value is `:atomic`. - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter to apply to records. This is also applied to a stream of inputs. - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. The default value is `:keyset`. - `:stream_with` - The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. The default value is `:filter`. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The action to use when building the read query. - `:assume_casted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting The default value is `false`. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:authorize_query_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Uses `authorize_with` if not set. - `:authorize_changeset_with` - If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error. Uses `authorize_with` if not set. - `:authorize_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. The default value is `:filter`. - `:sorted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to sort results by their input position, in cases where `return_records?: true` was provided. The default value is `false`. - `:return_records?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts. The default value is `false`. - `:return_errors?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the errors that occur. Defaults to false to account for large inserts. The default value is `false`. - `:batch_size` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100. - `:return_stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned. Potential elements: `{:notification, notification}` - if `return_notifications?` is set to `true` `{:ok, record}` - if `return_records?` is set to `true` `{:error, error}` - an error that occurred. May be changeset or an invidual error. The default value is `false`. - `:return_nothing?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Mutes warnings about returning nothing. Only relevant if `return_stream?` is set to `true` and all other `return_*?` options are set to `false`. The default value is `false`. - `:stop_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. The default value is `false`. - `:notify?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to generate any notifications. If this is set to `true` then the data layer must return the results from each batch. This may be intensive for large bulk actions. Notifications will be automatically sent unless `return_notifications?` is set to `true`. The default value is `false`. - `:transaction` - Whether or not to wrap the entire execution in a transaction, each batch, or not at all. Keep in mind: `before_transaction` and `after_transaction` hooks attached to changesets will have to be run *inside* the transaction if you choose `transaction: :all`. The default value is `:batch`. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously The default value is `0`. [](Ash.Resource.Interface.html#generic_action_opts/0) # generic\_action\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L232) Options supported by code interfaces for generic actions ## [](Ash.Resource.Interface.html#generic_action_opts/0-options)Options - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The actor for handling [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates, supplied to calculation context. - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - The tenant, supplied to calculation context. - `:authorize?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not the request should be authorized. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer, provided to the calculation context. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. [](Ash.Resource.Interface.html#get_opts/0) # get\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L188) Options supported by code interfaces for read actions with `get?` or `get_by` set. ## [](Ash.Resource.Interface.html#get_opts/0-options)Options - `:page` - Pagination options, see [`Ash.read/2`](Ash.html#read/2) for more. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the query - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. Valid values are :filter, :error The default value is `:filter`. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:query` - A query to seed the action with. - `:not_found_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return or raise a `NotFound` error or to return `nil` when a get? action/interface is called. - `:stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, a stream of the results will be returned The default value is `false`. - `:stream_options` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - Options passed to `Ash.stream!`, if `stream?: true` is given - `:batch_size` ([`integer/0`](../elixir/typespecs.html#basic-types)) - How many records to request in each query run. Defaults to the pagination limits on the resource, or 250. - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. The default value is `:keyset`. - `:stream_with` - The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. [](Ash.Resource.Interface.html#read_opts/0) # read\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L199) Options supported by code interfaces for read actions ## [](Ash.Resource.Interface.html#read_opts/0-options)Options - `:page` - Pagination options, see [`Ash.read/2`](Ash.html#read/2) for more. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the query - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. Valid values are :filter, :error The default value is `:filter`. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:query` - A query to seed the action with. - `:not_found_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return or raise a `NotFound` error or to return `nil` when a get? action/interface is called. - `:stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, a stream of the results will be returned The default value is `false`. - `:stream_options` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - Options passed to `Ash.stream!`, if `stream?: true` is given - `:batch_size` ([`integer/0`](../elixir/typespecs.html#basic-types)) - How many records to request in each query run. Defaults to the pagination limits on the resource, or 250. - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. The default value is `:keyset`. - `:stream_with` - The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. [](Ash.Resource.Interface.html#update_opts/0) # update\_opts() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/interface.ex#L210) Options supported by code interfaces for update actions ## [](Ash.Resource.Interface.html#update_opts/0-options)Options - `:params` ([`map/0`](../elixir/typespecs.html#basic-types)) - Parameters to supply, ignored if the input is a changeset, only used when an identifier is given. - `:atomic_upgrade?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true the action will be done atomically if it can (and is configured to do so), ignoring the in memory transformations and validations. You should not generally need to disable this. The default value is `true`. - `:timeout` ([`timeout/0`](../elixir/typespecs.html#built-in-types)) - A positive integer, or `:infinity`. If none is provided, the timeout configured on the domain is used. - `:tracer` (one or a list of module that adopts [`Ash.Tracer`](Ash.Tracer.html)) - A tracer that implements the [`Ash.Tracer`](Ash.Tracer.html) behaviour. See that module for more. - `:action` ([`term/0`](../elixir/typespecs.html#built-in-types)) - The action to use, either an Action struct or the name of the action - `:authorize?` - If an actor option is provided (even if it is `nil`), authorization happens automatically. If not, this flag can be used to authorize with no user. Valid values are true, false, nil - `:context` ([`map/0`](../elixir/typespecs.html#basic-types)) - Context to set on the query, changeset, or input - `:tenant` (value that implements the [`Ash.ToTenant`](Ash.ToTenant.html) protocol) - A tenant to set on the query or changeset - `:actor` ([`term/0`](../elixir/typespecs.html#built-in-types)) - If an actor is provided, it will be used in conjunction with the authorizers of a resource to authorize access - `:return_notifications?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Use this if you're running ash actions in your own transaction and you want to manually handle sending notifications. If a transaction is ongoing, and this is false, notifications will be discarded, otherwise the return value is `{:ok, result, notifications}` (or `{:ok, notifications}`) To send notifications later, use `Ash.Notifier.notify(notifications)`. It sends any notifications that can be sent, and returns the rest. The default value is `false`. - `:rollback_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to rollback the transaction on error, if the resource is in a transaction. If the action has `transaction? false` this option has no effect. If an error is returned from the data layer and the resource is in a transaction, the transaction is always rolled back, regardless. The default value is `true`. - `:notification_metadata` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Metadata to be merged into the metadata field for all notifications sent from this operation. The default value is `%{}`. - `:skip_unknown_inputs` - A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys. - `:load` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A load statement to add onto the changeset - `:bulk_options` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - Options passed to `Ash.bulk_create`, if a query, list, or stream of inputs is provided. - `:atomic_update` ([`map/0`](../elixir/typespecs.html#basic-types)) - A map of atomic updates to apply. See [`Ash.Changeset.atomic_update/3`](Ash.Changeset.html#atomic_update/3) for more. - `:stream_batch_size` ([`integer/0`](../elixir/typespecs.html#basic-types)) - Batch size to use if provided a query and the query must be streamed - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records if the `:stream` strategy is chosen. See the [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. The default value is `:keyset`. - `:authorize_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If a query is given, determines whether or not authorization is run on that query. The default value is `true`. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:filter` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A filter to apply to records. This is also applied to a stream of inputs. - `:strategy` - The strategy or strategies to enable. :stream is used in all cases if the data layer does not support atomics. The default value is `[:atomic]`. - `:allow_stream_with` - The 'worst' strategy allowed to be used to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. The default value is `:keyset`. - `:stream_with` - The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - The maximum number of processes allowed to be started for parallel loading of relationships and calculations. Defaults to `System.schedulers_online() * 2` - `:lock` ([`term/0`](../elixir/typespecs.html#built-in-types)) - A lock statement to add onto the query - `:return_query?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If `true`, the query that was ultimately used is returned as a third tuple element. The query goes through many potential changes during a request, potentially adding authorization filters, or replacing relationships for other data layers with their corresponding ids. This option can be used to get the true query that was sent to the data layer. The default value is `false`. - `:reuse_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer. The default value is `false`. - `:strict?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. See [`Ash.Query.load/2`](Ash.Query.html#load/2). The default value is `false`. - `:authorize_with` - If set to `:error`, instead of applying authorization filters as a filter, any records not matching the authroization filter will cause an error to be returned. The default value is `:filter`. - `:read_action` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The action to use when building the read query. - `:assume_casted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting The default value is `false`. - `:select` (list of [`atom/0`](../elixir/typespecs.html#basic-types)) - A select statement to apply to records. Ignored if `return_records?` is not true. - `:authorize_query_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. Uses `authorize_with` if not set. - `:authorize_changeset_with` - If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error. Uses `authorize_with` if not set. - `:authorize_with` - If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error. The default value is `:filter`. - `:sorted?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to sort results by their input position, in cases where `return_records?: true` was provided. The default value is `false`. - `:return_records?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts. The default value is `false`. - `:return_errors?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to return all of the errors that occur. Defaults to false to account for large inserts. The default value is `false`. - `:batch_size` ([`pos_integer/0`](../elixir/typespecs.html#basic-types)) - The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100. - `:return_stream?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned. Potential elements: `{:notification, notification}` - if `return_notifications?` is set to `true` `{:ok, record}` - if `return_records?` is set to `true` `{:error, error}` - an error that occurred. May be changeset or an invidual error. The default value is `false`. - `:return_nothing?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Mutes warnings about returning nothing. Only relevant if `return_stream?` is set to `true` and all other `return_*?` options are set to `false`. The default value is `false`. - `:stop_on_error?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If true, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped. The default value is `false`. - `:notify?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to generate any notifications. If this is set to `true` then the data layer must return the results from each batch. This may be intensive for large bulk actions. Notifications will be automatically sent unless `return_notifications?` is set to `true`. The default value is `false`. - `:transaction` - Whether or not to wrap the entire execution in a transaction, each batch, or not at all. Keep in mind: `before_transaction` and `after_transaction` hooks attached to changesets will have to be run *inside* the transaction if you choose `transaction: :all`. The default value is `:batch`. - `:max_concurrency` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously The default value is `0`. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualCreate.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_create.ex#L6 "View Source") The context passed into manual update action functions # [](Ash.Resource.ManualCreate.Context.html#summary)Summary ## [Types](Ash.Resource.ManualCreate.Context.html#types) [t()](Ash.Resource.ManualCreate.Context.html#t:t/0) # [](Ash.Resource.ManualCreate.Context.html#types)Types [](Ash.Resource.ManualCreate.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_create.ex#L24) ``` @type t() :: %Ash.Resource.ManualCreate.Context{ actor: any(), authorize?: boolean(), batch_size: pos_integer(), domain: Ash.Domain.t(), identity: Ash.Resource.Identity.t() | nil, return_records?: boolean(), select: [atom()], tenant: any(), tracer: [module()], upsert?: boolean(), upsert_fields: [atom()], upsert_keys: [atom()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualCreate behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_create.ex#L1 "View Source") A module to implement manual create actions. # [](Ash.Resource.ManualCreate.html#summary)Summary ## [Callbacks](Ash.Resource.ManualCreate.html#callbacks) [bulk\_create(changesets, opts, context)](Ash.Resource.ManualCreate.html#c:bulk_create/3) [create(changeset, opts, context)](Ash.Resource.ManualCreate.html#c:create/3) # [](Ash.Resource.ManualCreate.html#callbacks)Callbacks [](Ash.Resource.ManualCreate.html#c:bulk_create/3) # bulk\_create(changesets, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_create.ex#L49) ``` @callback bulk_create( changesets :: Enumerable.t(Ash.Changeset.t()), opts :: Keyword.t(), context :: Ash.Resource.ManualCreate.Context.t() ) :: [ :ok | {:ok, Ash.Resource.record()} | {:error, Ash.Error.t()} | {:notifications, [Ash.Notifier.Notification.t()]} ] ``` [](Ash.Resource.ManualCreate.html#c:create/3) # create(changeset, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_create.ex#L40) ``` @callback create( changeset :: Ash.Changeset.t(), opts :: Keyword.t(), context :: Ash.Resource.ManualCreate.Context.t() ) :: {:ok, Ash.Resource.record()} | {:ok, Ash.Resource.record(), %{notifications: [Ash.Notifier.Notification.t()]}} | {:error, term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualDestroy.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_destroy.ex#L8 "View Source") The context passed into manual update action functions # [](Ash.Resource.ManualDestroy.Context.html#summary)Summary ## [Types](Ash.Resource.ManualDestroy.Context.html#types) [t()](Ash.Resource.ManualDestroy.Context.html#t:t/0) # [](Ash.Resource.ManualDestroy.Context.html#types)Types [](Ash.Resource.ManualDestroy.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_destroy.ex#L22) ``` @type t() :: %Ash.Resource.ManualDestroy.Context{ actor: any(), authorize?: boolean(), batch_size: pos_integer(), domain: Ash.Domain.t(), return_records?: boolean(), select: [atom()], tenant: any(), tracer: [module()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualDestroy behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_destroy.ex#L1 "View Source") A module to implement manual destroy actions. Note that in the returns of these functions you must return the destroyed record or records. # [](Ash.Resource.ManualDestroy.html#summary)Summary ## [Callbacks](Ash.Resource.ManualDestroy.html#callbacks) [bulk\_destroy(changesets, opts, context)](Ash.Resource.ManualDestroy.html#c:bulk_destroy/3) [destroy(changeset, opts, context)](Ash.Resource.ManualDestroy.html#c:destroy/3) # [](Ash.Resource.ManualDestroy.html#callbacks)Callbacks [](Ash.Resource.ManualDestroy.html#c:bulk_destroy/3) # bulk\_destroy(changesets, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_destroy.ex#L43) ``` @callback bulk_destroy( changesets :: Enumerable.t(Ash.Changeset.t()), opts :: Keyword.t(), context :: Ash.Resource.ManualDestroy.Context.t() ) :: [ ok: Ash.Resource.record(), error: Ash.Error.t(), notifications: [Ash.Notifier.Notification.t()] ] ``` [](Ash.Resource.ManualDestroy.html#c:destroy/3) # destroy(changeset, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_destroy.ex#L34) ``` @callback destroy( changeset :: Ash.Changeset.t(), opts :: Keyword.t(), context :: Ash.Resource.ManualDestroy.Context.t() ) :: {:ok, Ash.Resource.record()} | {:ok, Ash.Resource.record(), [Ash.Notifier.Notification.t()]} | {:error, term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualRead behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_read.ex#L1 "View Source") A module to implement manual read actions. # [](Ash.Resource.ManualRead.html#summary)Summary ## [Types](Ash.Resource.ManualRead.html#types) [context()](Ash.Resource.ManualRead.html#t:context/0) ## [Callbacks](Ash.Resource.ManualRead.html#callbacks) [load\_relationships(query, results, opts, context, lazy?)](Ash.Resource.ManualRead.html#c:load_relationships/5) [read(query, data\_layer\_query, opts, context)](Ash.Resource.ManualRead.html#c:read/4) # [](Ash.Resource.ManualRead.html#types)Types [](Ash.Resource.ManualRead.html#t:context/0) # context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_read.ex#L6) ``` @type context() :: %{ optional(:actor) => term(), optional(:tenant) => term(), optional(:authorize?) => boolean(), optional(:domain) => module(), optional(any()) => any() } ``` # [](Ash.Resource.ManualRead.html#callbacks)Callbacks [](Ash.Resource.ManualRead.html#c:load_relationships/5) # load\_relationships(query, results, opts, context, lazy?) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_read.ex#L14) ``` @callback load_relationships( query :: Ash.Query.t(), results :: [Ash.Resource.record()], opts :: Keyword.t(), context :: context(), lazy? :: boolean() ) :: {:ok, [Ash.Resource.record()]} | {:error, term()} ``` [](Ash.Resource.ManualRead.html#c:read/4) # read(query, data\_layer\_query, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_read.ex#L23) ``` @callback read( query :: Ash.Query.t(), data_layer_query :: term(), opts :: Keyword.t(), context :: context() ) :: {:ok, [Ash.Resource.record()]} | {:error, term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualRelationship.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_relationship/manual_relationship.ex#L6 "View Source") The context passed into manual relationship functions # [](Ash.Resource.ManualRelationship.Context.html#summary)Summary ## [Types](Ash.Resource.ManualRelationship.Context.html#types) [t()](Ash.Resource.ManualRelationship.Context.html#t:t/0) # [](Ash.Resource.ManualRelationship.Context.html#types)Types [](Ash.Resource.ManualRelationship.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_relationship/manual_relationship.ex#L17) ``` @type t() :: %Ash.Resource.ManualRelationship.Context{ actor: term(), authorize?: boolean(), domain: module(), query: Ash.Query.t(), relationship: Ash.Resource.Relationships.relationship(), tenant: term() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualRelationship behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_relationship/manual_relationship.ex#L1 "View Source") A module to implement manual relationships. # [](Ash.Resource.ManualRelationship.html#summary)Summary ## [Callbacks](Ash.Resource.ManualRelationship.html#callbacks) [load(list, opts, context)](Ash.Resource.ManualRelationship.html#c:load/3) [select(opts)](Ash.Resource.ManualRelationship.html#c:select/1) # [](Ash.Resource.ManualRelationship.html#callbacks)Callbacks [](Ash.Resource.ManualRelationship.html#c:load/3) # load(list, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_relationship/manual_relationship.ex#L29) ``` @callback load( [Ash.Resource.record()], opts :: Keyword.t(), context :: Ash.Resource.ManualRelationship.Context.t() ) :: {:ok, map()} | {:error, term()} ``` [](Ash.Resource.ManualRelationship.html#c:select/1) # select(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_relationship/manual_relationship.ex#L27) ``` @callback select(opts :: Keyword.t()) :: [atom()] ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualUpdate.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_update.ex#L6 "View Source") The context passed into manual update action functions # [](Ash.Resource.ManualUpdate.Context.html#summary)Summary ## [Types](Ash.Resource.ManualUpdate.Context.html#types) [t()](Ash.Resource.ManualUpdate.Context.html#t:t/0) # [](Ash.Resource.ManualUpdate.Context.html#types)Types [](Ash.Resource.ManualUpdate.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_update.ex#L20) ``` @type t() :: %Ash.Resource.ManualUpdate.Context{ actor: any(), authorize?: boolean(), batch_size: pos_integer(), domain: Ash.Domain.t(), return_records?: boolean(), select: [atom()], tenant: any(), tracer: [module()] } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.ManualUpdate behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_update.ex#L1 "View Source") A module to implement manual update actions. # [](Ash.Resource.ManualUpdate.html#summary)Summary ## [Callbacks](Ash.Resource.ManualUpdate.html#callbacks) [bulk\_update(changesets, opts, context)](Ash.Resource.ManualUpdate.html#c:bulk_update/3) [update(changeset, opts, context)](Ash.Resource.ManualUpdate.html#c:update/3) # [](Ash.Resource.ManualUpdate.html#callbacks)Callbacks [](Ash.Resource.ManualUpdate.html#c:bulk_update/3) # bulk\_update(changesets, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_update.ex#L41) ``` @callback bulk_update( changesets :: Enumerable.t(Ash.Changeset.t()), opts :: Keyword.t(), context :: Ash.Resource.ManualUpdate.Context.t() ) :: [ :ok | {:ok, Ash.Resource.record()} | {:error, Ash.Error.t()} | {:notifications, [Ash.Notifier.Notification.t()]} ] ``` [](Ash.Resource.ManualUpdate.html#c:update/3) # update(changeset, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/manual_actions/manual_update.ex#L32) ``` @callback update( changeset :: Ash.Changeset.t(), opts :: Keyword.t(), context :: Ash.Resource.ManualUpdate.Context.t() ) :: {:ok, Ash.Resource.record()} | {:ok, Ash.Resource.record(), %{notifications: [Ash.Notifier.Notification.t()]}} | {:error, term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Preparation.Builtins (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/builtins.ex#L1 "View Source") Builtin query preparations # [](Ash.Resource.Preparation.Builtins.html#summary)Summary ## [Functions](Ash.Resource.Preparation.Builtins.html#functions) [after\_action(callback)](Ash.Resource.Preparation.Builtins.html#after_action/1) Directly attach an `after_action` function to the query. [before\_action(callback)](Ash.Resource.Preparation.Builtins.html#before_action/1) Directly attach a `before_action` function to the query. [build(options)](Ash.Resource.Preparation.Builtins.html#build/1) Passes the given keyword list to [`Ash.Query.build/2`](Ash.Query.html#build/2) with the query being prepared. [set\_context(context)](Ash.Resource.Preparation.Builtins.html#set_context/1) Merges the given query context. # [](Ash.Resource.Preparation.Builtins.html#functions)Functions [](Ash.Resource.Preparation.Builtins.html#after_action/1) # after\_action(callback) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/builtins.ex#L78) Directly attach an `after_action` function to the query. This function will be called by [`Ash.Query.after_action/2`](Ash.Query.html#after_action/2), with an additional `context` argument. ## [](Ash.Resource.Preparation.Builtins.html#after_action/1-example)Example ``` prepare after_action(fn query, records, _context -> Logger.debug("Query for #{query.action.name} on resource #{inspect(query.resource)} returned #{length(records)} records") {:ok, records} end) ``` [](Ash.Resource.Preparation.Builtins.html#before_action/1) # before\_action(callback) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/builtins.ex#L53) Directly attach a `before_action` function to the query. This function will be called by [`Ash.Query.before_action/2`](Ash.Query.html#before_action/2), with an additional `context` argument. ## [](Ash.Resource.Preparation.Builtins.html#before_action/1-example)Example ``` prepare before_action(fn query, _context -> Logger.debug("About to execute query for #{query.action.name} on #{inspect(query.resource)}") query end) ``` [](Ash.Resource.Preparation.Builtins.html#build/1) # build(options) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/builtins.ex#L35) ``` @spec build(Keyword.t()) :: Ash.Resource.Preparation.ref() ``` Passes the given keyword list to [`Ash.Query.build/2`](Ash.Query.html#build/2) with the query being prepared. This allows declaring simple query modifications in-line. To see the available options, see [`Ash.Query.build/2`](Ash.Query.html#build/2) ## [](Ash.Resource.Preparation.Builtins.html#build/1-examples)Examples ``` prepare build(sort: [song_rank: :desc], limit: 10) prepare build(load: [:friends]) ``` [](Ash.Resource.Preparation.Builtins.html#set_context/1) # set\_context(context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/builtins.ex#L17) ``` @spec set_context(context :: map() | mfa()) :: Ash.Resource.Preparation.ref() ``` Merges the given query context. If an MFA is provided, it will be called with the changeset. The MFA should return `{:ok, context_to_be_merged}` or `{:error, term}` ## [](Ash.Resource.Preparation.Builtins.html#set_context/1-examples)Examples ``` change set_context(%{something_used_internally: true}) change set_context({MyApp.Context, :set_context, []}) ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Preparation.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/preparation.ex#L50 "View Source") The context for a preparation. # [](Ash.Resource.Preparation.Context.html#summary)Summary ## [Types](Ash.Resource.Preparation.Context.html#types) [t()](Ash.Resource.Preparation.Context.html#t:t/0) # [](Ash.Resource.Preparation.Context.html#types)Types [](Ash.Resource.Preparation.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/preparation.ex#L56) ``` @type t() :: %Ash.Resource.Preparation.Context{ actor: Ash.Resource.record() | nil, authorize?: boolean() | nil, tenant: term(), tracer: Ash.Tracer.t() | [Ash.Tracer.t()] | nil } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Preparation behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/preparation.ex#L1 "View Source") The behaviour for an action-specific query preparation. [`init/1`](Ash.Resource.Preparation.html#c:init/1) is defined automatically by `use Ash.Resource.Preparation`, but can be implemented if you want to validate/transform any options passed to the module. The main function is [`prepare/3`](Ash.Resource.Preparation.html#c:prepare/3). It takes the query, any options that were provided when this preparation was configured on a resource, and the context, which currently only has the actor. To access any query arguments from within a preparation, make sure you are using [`Ash.Query.get_argument/2`](Ash.Query.html#get_argument/2) as the argument keys may be strings or atoms. # [](Ash.Resource.Preparation.html#summary)Summary ## [Types](Ash.Resource.Preparation.html#types) [ref()](Ash.Resource.Preparation.html#t:ref/0) [t()](Ash.Resource.Preparation.html#t:t/0) ## [Callbacks](Ash.Resource.Preparation.html#callbacks) [init(opts)](Ash.Resource.Preparation.html#c:init/1) [prepare(query, opts, context)](Ash.Resource.Preparation.html#c:prepare/3) # [](Ash.Resource.Preparation.html#types)Types [](Ash.Resource.Preparation.html#t:ref/0) # ref() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/preparation.ex#L18) ``` @type ref() :: {module(), Keyword.t()} | module() ``` [](Ash.Resource.Preparation.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/preparation.ex#L17) ``` @type t() :: %Ash.Resource.Preparation{preparation: term()} ``` # [](Ash.Resource.Preparation.html#callbacks)Callbacks [](Ash.Resource.Preparation.html#c:init/1) # init(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/preparation.ex#L64) ``` @callback init(opts :: Keyword.t()) :: {:ok, Keyword.t()} | {:error, term()} ``` [](Ash.Resource.Preparation.html#c:prepare/3) # prepare(query, opts, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/preparation/preparation.ex#L65) ``` @callback prepare( query :: Ash.Query.t(), opts :: Keyword.t(), context :: Ash.Resource.Preparation.Context.t() ) :: Ash.Query.t() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Relationships.BelongsTo (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/belongs_to.ex#L1 "View Source") Represents a belongs\_to relationship on a resource # [](Ash.Resource.Relationships.BelongsTo.html#summary)Summary ## [Types](Ash.Resource.Relationships.BelongsTo.html#types) [t()](Ash.Resource.Relationships.BelongsTo.html#t:t/0) # [](Ash.Resource.Relationships.BelongsTo.html#types)Types [](Ash.Resource.Relationships.BelongsTo.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/belongs_to.ex#L36) ``` @type t() :: %Ash.Resource.Relationships.BelongsTo{ allow_forbidden_field?: term(), allow_nil?: boolean(), attribute_public?: boolean(), attribute_type: term(), attribute_writable?: boolean(), authorize_read_with: term(), cardinality: :one, context: term(), define_attribute?: boolean(), description: String.t(), destination: Ash.Resource.t(), destination_attribute: atom(), domain: term(), filter: Ash.Filter.t() | nil, filterable?: boolean(), filters: [any()], name: atom(), not_found_message: term(), primary_key?: boolean(), public?: boolean(), read_action: atom(), sort: term(), sortable?: boolean(), source: Ash.Resource.t(), source_attribute: atom() | nil, type: :belongs_to, validate_destination_attribute?: term(), violation_message: term(), writable?: boolean() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Relationships.HasMany (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/has_many.ex#L1 "View Source") Represents a has\_many relationship on a resource # [](Ash.Resource.Relationships.HasMany.html#summary)Summary ## [Types](Ash.Resource.Relationships.HasMany.html#types) [t()](Ash.Resource.Relationships.HasMany.html#t:t/0) ## [Functions](Ash.Resource.Relationships.HasMany.html#functions) [manual(module)](Ash.Resource.Relationships.HasMany.html#manual/1) [transform(relationship)](Ash.Resource.Relationships.HasMany.html#transform/1) # [](Ash.Resource.Relationships.HasMany.html#types)Types [](Ash.Resource.Relationships.HasMany.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/has_many.ex#L33) ``` @type t() :: %Ash.Resource.Relationships.HasMany{ allow_forbidden_field?: term(), authorize_read_with: term(), autogenerated_join_relationship_of: atom() | nil, cardinality: :many, context: term(), could_be_related_at_creation?: term(), description: String.t(), destination: Ash.Resource.t(), destination_attribute: atom(), domain: term(), filter: Ash.Filter.t() | nil, filterable?: boolean(), filters: [any()], manual: atom() | {atom(), Keyword.t()} | nil, name: atom(), no_attributes?: boolean(), not_found_message: term(), public?: boolean(), read_action: atom(), sort: term(), sortable?: true, source: Ash.Resource.t(), source_attribute: atom(), type: :has_many, validate_destination_attribute?: term(), violation_message: term(), writable?: boolean() } ``` # [](Ash.Resource.Relationships.HasMany.html#functions)Functions [](Ash.Resource.Relationships.HasMany.html#manual/1) # manual(module) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/has_many.ex#L72) [](Ash.Resource.Relationships.HasMany.html#transform/1) # transform(relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/has_many.ex#L77) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Relationships.HasOne (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/has_one.ex#L1 "View Source") Represents a has\_one relationship on a resource # [](Ash.Resource.Relationships.HasOne.html#summary)Summary ## [Types](Ash.Resource.Relationships.HasOne.html#types) [t()](Ash.Resource.Relationships.HasOne.html#t:t/0) ## [Functions](Ash.Resource.Relationships.HasOne.html#functions) [transform(relationship)](Ash.Resource.Relationships.HasOne.html#transform/1) # [](Ash.Resource.Relationships.HasOne.html#types)Types [](Ash.Resource.Relationships.HasOne.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/has_one.ex#L36) ``` @type t() :: %Ash.Resource.Relationships.HasOne{ allow_forbidden_field?: term(), allow_nil?: term(), allow_orphans?: boolean(), authorize_read_with: term(), cardinality: :one, context: term(), could_be_related_at_creation?: term(), description: String.t(), destination: Ash.Resource.t(), destination_attribute: atom(), domain: term(), filter: Ash.Filter.t() | nil, filterable?: boolean(), filters: [any()], from_many?: boolean(), manual: atom() | {atom(), Keyword.t()} | nil, name: atom(), no_attributes?: boolean(), not_found_message: term(), public?: boolean(), read_action: atom(), sort: term(), sortable?: boolean(), source: Ash.Resource.t(), source_attribute: atom(), type: :has_one, validate_destination_attribute?: term(), violation_message: term(), writable?: boolean() } ``` # [](Ash.Resource.Relationships.HasOne.html#functions)Functions [](Ash.Resource.Relationships.HasOne.html#transform/1) # transform(relationship) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/has_one.ex#L89) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Relationships (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/relationships.ex#L1 "View Source") Types Ash relationships # [](Ash.Resource.Relationships.html#summary)Summary ## [Types](Ash.Resource.Relationships.html#types) [cardinality()](Ash.Resource.Relationships.html#t:cardinality/0) [relationship()](Ash.Resource.Relationships.html#t:relationship/0) [type()](Ash.Resource.Relationships.html#t:type/0) # [](Ash.Resource.Relationships.html#types)Types [](Ash.Resource.Relationships.html#t:cardinality/0) # cardinality() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/relationships.ex#L7) ``` @type cardinality() :: :many | :one ``` [](Ash.Resource.Relationships.html#t:relationship/0) # relationship() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/relationships.ex#L5) ``` @type relationship() :: Ash.Resource.Relationships.HasOne.t() | Ash.Resource.Relationships.BelongsTo.t() | Ash.Resource.Relationships.HasMany.t() | Ash.Resource.Relationships.ManyToMany.t() ``` [](Ash.Resource.Relationships.html#t:type/0) # type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/relationships.ex#L6) ``` @type type() :: :has_many | :has_one | :belongs_to | :many_to_many ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Relationships.ManyToMany (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/many_to_many.ex#L1 "View Source") Represents a many\_to\_many relationship on a resource # [](Ash.Resource.Relationships.ManyToMany.html#summary)Summary ## [Types](Ash.Resource.Relationships.ManyToMany.html#types) [t()](Ash.Resource.Relationships.ManyToMany.html#t:t/0) # [](Ash.Resource.Relationships.ManyToMany.html#types)Types [](Ash.Resource.Relationships.ManyToMany.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/relationships/many_to_many.ex#L34) ``` @type t() :: %Ash.Resource.Relationships.ManyToMany{ allow_forbidden_field?: term(), authorize_read_with: term(), cardinality: :many, context: term(), could_be_related_at_creation?: term(), description: String.t(), destination: Ash.Resource.t(), destination_attribute: atom(), destination_attribute_on_join_resource: atom(), domain: term(), filter: Ash.Filter.t() | nil, filterable?: boolean(), filters: [any()], has_many: boolean(), join_relationship: atom(), name: atom(), not_found_message: term(), public?: boolean(), read_action: atom(), sort: term(), sortable?: boolean(), source: Ash.Resource.t(), source_attribute: atom(), source_attribute_on_join_resource: atom(), through: Ash.Resource.t(), type: :many_to_many, validate_destination_attribute?: term(), violation_message: term() } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.AttributesByName (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/attributes_by_name.ex#L1 "View Source") Persists attribute\_names and attributes\_by\_name. # [](Ash.Resource.Transformers.AttributesByName.html#summary)Summary ## [Functions](Ash.Resource.Transformers.AttributesByName.html#functions) [after?(\_)](Ash.Resource.Transformers.AttributesByName.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.AttributesByName.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.AttributesByName.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.AttributesByName.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.AttributesByName.html#functions)Functions [](Ash.Resource.Transformers.AttributesByName.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/attributes_by_name.ex#L9) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.AttributesByName.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/attributes_by_name.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.AttributesByName.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/attributes_by_name.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.AttributesByName.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/attributes_by_name.ex#L11) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.BelongsToAttribute (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/belongs_to_attribute.ex#L1 "View Source") Creates the attribute for belongs\_to relationships that have `define_attribute?: true` # [](Ash.Resource.Transformers.BelongsToAttribute.html#summary)Summary ## [Functions](Ash.Resource.Transformers.BelongsToAttribute.html#functions) [after?(\_)](Ash.Resource.Transformers.BelongsToAttribute.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.BelongsToAttribute.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.BelongsToAttribute.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.BelongsToAttribute.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.BelongsToAttribute.html#functions)Functions [](Ash.Resource.Transformers.BelongsToAttribute.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/belongs_to_attribute.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.BelongsToAttribute.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/belongs_to_attribute.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.BelongsToAttribute.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/belongs_to_attribute.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.BelongsToAttribute.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/belongs_to_attribute.ex#L13) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.CacheActionInputs (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_action_inputs.ex#L1 "View Source") Stores the set of valid input keys for each action # [](Ash.Resource.Transformers.CacheActionInputs.html#summary)Summary ## [Functions](Ash.Resource.Transformers.CacheActionInputs.html#functions) [after?(\_)](Ash.Resource.Transformers.CacheActionInputs.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.CacheActionInputs.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.CacheActionInputs.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.CacheActionInputs.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.CacheActionInputs.html#functions)Functions [](Ash.Resource.Transformers.CacheActionInputs.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_action_inputs.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.CacheActionInputs.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_action_inputs.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.CacheActionInputs.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_action_inputs.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.CacheActionInputs.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_action_inputs.ex#L7) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.CacheCalculations (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_calculations.ex#L1 "View Source") Persists commonly used calculation information. # [](Ash.Resource.Transformers.CacheCalculations.html#summary)Summary ## [Functions](Ash.Resource.Transformers.CacheCalculations.html#functions) [after?(\_)](Ash.Resource.Transformers.CacheCalculations.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.CacheCalculations.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.CacheCalculations.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.CacheCalculations.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.CacheCalculations.html#functions)Functions [](Ash.Resource.Transformers.CacheCalculations.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_calculations.ex#L9) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.CacheCalculations.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_calculations.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.CacheCalculations.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_calculations.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.CacheCalculations.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_calculations.ex#L11) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.CachePrimaryKey (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_primary_key.ex#L1 "View Source") Validates and caches the primary key of a resource # [](Ash.Resource.Transformers.CachePrimaryKey.html#summary)Summary ## [Functions](Ash.Resource.Transformers.CachePrimaryKey.html#functions) [after?(arg1)](Ash.Resource.Transformers.CachePrimaryKey.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.CachePrimaryKey.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.CachePrimaryKey.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.CachePrimaryKey.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.CachePrimaryKey.html#functions)Functions [](Ash.Resource.Transformers.CachePrimaryKey.html#after?/1) # after?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_primary_key.ex#L53) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.CachePrimaryKey.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_primary_key.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.CachePrimaryKey.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_primary_key.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.CachePrimaryKey.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_primary_key.ex#L8) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.CacheRelationships (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_relationships.ex#L1 "View Source") Persists commonly used relationship information. # [](Ash.Resource.Transformers.CacheRelationships.html#summary)Summary ## [Functions](Ash.Resource.Transformers.CacheRelationships.html#functions) [after?(\_)](Ash.Resource.Transformers.CacheRelationships.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.CacheRelationships.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.CacheRelationships.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.CacheRelationships.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.CacheRelationships.html#functions)Functions [](Ash.Resource.Transformers.CacheRelationships.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_relationships.ex#L9) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.CacheRelationships.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_relationships.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.CacheRelationships.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_relationships.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.CacheRelationships.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_relationships.ex#L11) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.CacheUniqueKeys (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_unique_keys.ex#L1 "View Source") Stores the set of unique keys for a resource # [](Ash.Resource.Transformers.CacheUniqueKeys.html#summary)Summary ## [Functions](Ash.Resource.Transformers.CacheUniqueKeys.html#functions) [after?(\_)](Ash.Resource.Transformers.CacheUniqueKeys.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.CacheUniqueKeys.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.CacheUniqueKeys.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.CacheUniqueKeys.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.CacheUniqueKeys.html#functions)Functions [](Ash.Resource.Transformers.CacheUniqueKeys.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_unique_keys.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.CacheUniqueKeys.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_unique_keys.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.CacheUniqueKeys.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_unique_keys.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.CacheUniqueKeys.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/cache_unique_keys.ex#L7) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.CreateJoinRelationship (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/create_join_relationship.ex#L1 "View Source") Creates an automatically named `has_many` relationship for each many\_to\_many. # [](Ash.Resource.Transformers.CreateJoinRelationship.html#summary)Summary ## [Functions](Ash.Resource.Transformers.CreateJoinRelationship.html#functions) [after?(\_)](Ash.Resource.Transformers.CreateJoinRelationship.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.CreateJoinRelationship.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(arg1)](Ash.Resource.Transformers.CreateJoinRelationship.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.CreateJoinRelationship.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.CreateJoinRelationship.html#functions)Functions [](Ash.Resource.Transformers.CreateJoinRelationship.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/create_join_relationship.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.CreateJoinRelationship.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/create_join_relationship.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.CreateJoinRelationship.html#before?/1) # before?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/create_join_relationship.ex#L89) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.CreateJoinRelationship.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/create_join_relationship.ex#L11) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.DefaultAccept (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/default_accept.ex#L1 "View Source") Sets the default `accept` for each action # [](Ash.Resource.Transformers.DefaultAccept.html#summary)Summary ## [Functions](Ash.Resource.Transformers.DefaultAccept.html#functions) [after?(arg1)](Ash.Resource.Transformers.DefaultAccept.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.DefaultAccept.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.DefaultAccept.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.DefaultAccept.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.DefaultAccept.html#functions)Functions [](Ash.Resource.Transformers.DefaultAccept.html#after?/1) # after?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/default_accept.ex#L143) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.DefaultAccept.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/default_accept.ex#L4) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.DefaultAccept.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/default_accept.ex#L4) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.DefaultAccept.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/default_accept.ex#L8) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.GetByReadActions (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/get_by_read_actions.ex#L1 "View Source") Transform any read actions which contain a `get_by` option. # [](Ash.Resource.Transformers.GetByReadActions.html#summary)Summary ## [Functions](Ash.Resource.Transformers.GetByReadActions.html#functions) [after\_compile?()](Ash.Resource.Transformers.GetByReadActions.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). # [](Ash.Resource.Transformers.GetByReadActions.html#functions)Functions [](Ash.Resource.Transformers.GetByReadActions.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/get_by_read_actions.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.HasDestinationField (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/has_destination_field.ex#L1 "View Source") Guesses the `destination_attribute` for has many and has one relationships unless provided # [](Ash.Resource.Transformers.HasDestinationField.html#summary)Summary ## [Functions](Ash.Resource.Transformers.HasDestinationField.html#functions) [after?(\_)](Ash.Resource.Transformers.HasDestinationField.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.HasDestinationField.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.HasDestinationField.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.HasDestinationField.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.HasDestinationField.html#functions)Functions [](Ash.Resource.Transformers.HasDestinationField.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/has_destination_field.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.HasDestinationField.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/has_destination_field.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.HasDestinationField.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/has_destination_field.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.HasDestinationField.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/has_destination_field.ex#L7) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_destination_attribute_on_join_resource.ex#L1 "View Source") Guesses the `destination_attribute_on_join_resource` for many to many relationships unless provided. # [](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#summary)Summary ## [Functions](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#functions) [after?(\_)](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#functions)Functions [](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_destination_attribute_on_join_resource.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_destination_attribute_on_join_resource.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_destination_attribute_on_join_resource.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.ManyToManyDestinationAttributeOnJoinResource.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_destination_attribute_on_join_resource.ex#L10) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_source_attribute_on_join_resource.ex#L1 "View Source") Guesses the `source_attribute_on_join_resource` for many to many relationships unless provided. # [](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#summary)Summary ## [Functions](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#functions) [after?(\_)](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#functions)Functions [](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_source_attribute_on_join_resource.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_source_attribute_on_join_resource.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_source_attribute_on_join_resource.ex#L6) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.ManyToManySourceAttributeOnJoinResource.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/many_to_many_source_attribute_on_join_resource.ex#L10) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.RequireUniqueActionNames (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_action_names.ex#L1 "View Source") Ensures that all actions have unique names. # [](Ash.Resource.Transformers.RequireUniqueActionNames.html#summary)Summary ## [Functions](Ash.Resource.Transformers.RequireUniqueActionNames.html#functions) [after?(arg1)](Ash.Resource.Transformers.RequireUniqueActionNames.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.RequireUniqueActionNames.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.RequireUniqueActionNames.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.RequireUniqueActionNames.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.RequireUniqueActionNames.html#functions)Functions [](Ash.Resource.Transformers.RequireUniqueActionNames.html#after?/1) # after?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_action_names.ex#L32) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.RequireUniqueActionNames.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_action_names.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.RequireUniqueActionNames.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_action_names.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.RequireUniqueActionNames.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_action_names.ex#L10) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.RequireUniqueFieldNames (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_field_names.ex#L1 "View Source") Confirms that a resource does not have multiple fields(attributes, calculations, aggregates, and relationships) with the same name. # [](Ash.Resource.Transformers.RequireUniqueFieldNames.html#summary)Summary ## [Functions](Ash.Resource.Transformers.RequireUniqueFieldNames.html#functions) [after?(arg1)](Ash.Resource.Transformers.RequireUniqueFieldNames.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.RequireUniqueFieldNames.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.RequireUniqueFieldNames.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.RequireUniqueFieldNames.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.RequireUniqueFieldNames.html#functions)Functions [](Ash.Resource.Transformers.RequireUniqueFieldNames.html#after?/1) # after?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_field_names.ex#L47) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.RequireUniqueFieldNames.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_field_names.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.RequireUniqueFieldNames.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_field_names.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.RequireUniqueFieldNames.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/require_unique_field_names.ex#L10) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.SetPrimaryActions (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_primary_actions.ex#L1 "View Source") Validates the primary action configuration If multiple primary actions exist this results in an error. # [](Ash.Resource.Transformers.SetPrimaryActions.html#summary)Summary ## [Functions](Ash.Resource.Transformers.SetPrimaryActions.html#functions) [after?(arg1)](Ash.Resource.Transformers.SetPrimaryActions.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.SetPrimaryActions.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.SetPrimaryActions.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.SetPrimaryActions.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.SetPrimaryActions.html#functions)Functions [](Ash.Resource.Transformers.SetPrimaryActions.html#after?/1) # after?(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_primary_actions.ex#L12) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.SetPrimaryActions.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_primary_actions.ex#L7) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.SetPrimaryActions.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_primary_actions.ex#L7) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.SetPrimaryActions.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_primary_actions.ex#L15) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.SetRelationshipSource (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_relationship_source.ex#L1 "View Source") Sets the `source` key on relationships to be the resource they were defined on # [](Ash.Resource.Transformers.SetRelationshipSource.html#summary)Summary ## [Functions](Ash.Resource.Transformers.SetRelationshipSource.html#functions) [after?(\_)](Ash.Resource.Transformers.SetRelationshipSource.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.SetRelationshipSource.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.SetRelationshipSource.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.SetRelationshipSource.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.SetRelationshipSource.html#functions)Functions [](Ash.Resource.Transformers.SetRelationshipSource.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_relationship_source.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.SetRelationshipSource.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_relationship_source.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.SetRelationshipSource.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_relationship_source.ex#L3) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.SetRelationshipSource.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/set_relationship_source.ex#L7) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Transformers.ValidationsAndChangesForType (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/validations_and_changes_for_type.ex#L1 "View Source") Persists global changes/validations and what type they go on. # [](Ash.Resource.Transformers.ValidationsAndChangesForType.html#summary)Summary ## [Functions](Ash.Resource.Transformers.ValidationsAndChangesForType.html#functions) [after?(\_)](Ash.Resource.Transformers.ValidationsAndChangesForType.html#after?/1) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [after\_compile?()](Ash.Resource.Transformers.ValidationsAndChangesForType.html#after_compile?/0) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [before?(\_)](Ash.Resource.Transformers.ValidationsAndChangesForType.html#before?/1) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [transform(dsl\_state)](Ash.Resource.Transformers.ValidationsAndChangesForType.html#transform/1) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). # [](Ash.Resource.Transformers.ValidationsAndChangesForType.html#functions)Functions [](Ash.Resource.Transformers.ValidationsAndChangesForType.html#after?/1) # after?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/validations_and_changes_for_type.ex#L9) Callback implementation for [`Spark.Dsl.Transformer.after?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after?/1). [](Ash.Resource.Transformers.ValidationsAndChangesForType.html#after_compile?/0) # after\_compile?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/validations_and_changes_for_type.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.after_compile?/0`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:after_compile?/0). [](Ash.Resource.Transformers.ValidationsAndChangesForType.html#before?/1) # before?(\_) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/validations_and_changes_for_type.ex#L5) Callback implementation for [`Spark.Dsl.Transformer.before?/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:before?/1). [](Ash.Resource.Transformers.ValidationsAndChangesForType.html#transform/1) # transform(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/transformers/validations_and_changes_for_type.ex#L11) Callback implementation for [`Spark.Dsl.Transformer.transform/1`](../spark/2.2.40/Spark.Dsl.Transformer.html#c:transform/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Validation.ActionIs (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/action_is.ex#L1 "View Source") Validates that the action is the specified action. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Validation.Builtins (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L1 "View Source") Built in validations that are available to all resources The functions in this module are imported by default in the validations section. # [](Ash.Resource.Validation.Builtins.html#summary)Summary ## [Functions](Ash.Resource.Validation.Builtins.html#functions) [absent(attributes, opts \\\\ \[\])](Ash.Resource.Validation.Builtins.html#absent/2) Validates that the given attribute or argument or list of attributes or arguments are `nil`. [action\_is(action)](Ash.Resource.Validation.Builtins.html#action_is/1) Validates that the action is a specific action. Primarily meant for use in `where`. [argument\_does\_not\_equal(argument, value)](Ash.Resource.Validation.Builtins.html#argument_does_not_equal/2) Validates that an argument is not being changed to a specific value, or does not equal the given value if it is not being changed. [argument\_equals(argument, value)](Ash.Resource.Validation.Builtins.html#argument_equals/2) Validates that an argument is being changed to a specific value, or equals the given value if it is not being changed. [argument\_in(argument, list)](Ash.Resource.Validation.Builtins.html#argument_in/2) Validates that an argument is being changed to one of a set of specific values, or is in the the given list if it is not being changed. [attribute\_does\_not\_equal(attribute, value)](Ash.Resource.Validation.Builtins.html#attribute_does_not_equal/2) Validates that an attribute is not being changed to a specific value, or does not equal the given value if it is not being changed. [attribute\_equals(attribute, value)](Ash.Resource.Validation.Builtins.html#attribute_equals/2) Validates that an attribute is being changed to a specific value, or equals the given value if it is not being changed. [attribute\_in(attribute, list)](Ash.Resource.Validation.Builtins.html#attribute_in/2) Validates that an attribute is being changed to one of a set of specific values, or is in the the given list if it is not being changed. [attributes\_absent(attributes, opts \\\\ \[\])](Ash.Resource.Validation.Builtins.html#attributes_absent/2) Validates that the attribute or list of attributes are `nil`. See [`absent/2`](Ash.Resource.Validation.Builtins.html#absent/2) for more information. [attributes\_present(attributes, opts \\\\ \[\])](Ash.Resource.Validation.Builtins.html#attributes_present/2) Validates that the attribute or list of attributes are not `nil`. See [`present/2`](Ash.Resource.Validation.Builtins.html#present/2) for more information. [changing(field)](Ash.Resource.Validation.Builtins.html#changing/1) Validates that an attribute or relationship is being changed [compare(attribute, opts \\\\ \[\])](Ash.Resource.Validation.Builtins.html#compare/2) Validates that an attribute or argument meets the given comparison criteria. [confirm(field, confirmation)](Ash.Resource.Validation.Builtins.html#confirm/2) Validates that a field or argument matches another field or argument [match(attribute, match)](Ash.Resource.Validation.Builtins.html#match/2) Validates that an attribute's value matches a given regex. [negate(validation)](Ash.Resource.Validation.Builtins.html#negate/1) Validates that other validation does not pass [numericality(attribute, opts \\\\ \[\])](Ash.Resource.Validation.Builtins.html#numericality/2) Validates that an attribute or argument meets the given comparison criteria. [one\_of(attribute, values)](Ash.Resource.Validation.Builtins.html#one_of/2) Validates that an attribute's value is in a given list [present(attributes, opts \\\\ \[\])](Ash.Resource.Validation.Builtins.html#present/2) Validates that the given attribute or argument or list of attributes or arguments are not `nil`. [string\_length(attribute, opts \\\\ \[\])](Ash.Resource.Validation.Builtins.html#string_length/2) Validates that an attribute on the original record meets the given length criteria # [](Ash.Resource.Validation.Builtins.html#functions)Functions [](Ash.Resource.Validation.Builtins.html#absent/2) # absent(attributes, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L258) ``` @spec absent(attributes_or_arguments :: atom() | [atom()], opts :: Keyword.t()) :: Ash.Resource.Validation.ref() ``` Validates that the given attribute or argument or list of attributes or arguments are `nil`. This is the inverse of [`present/2`](Ash.Resource.Validation.Builtins.html#present/2). Use options to specify how many must be `nil`. If no options are provided, validates that they are all absent. Keep in mind that some types cast certain values to `nil`, and validations are applied after all inputs have been cast. For example, a `:string` type attribute with the default constraints will cast `""` as `nil`, meaning an input of `""` would pass the `absent` validation. ## [](Ash.Resource.Validation.Builtins.html#absent/2-options)Options - `:at_least` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At least this many must be absent. Defaults to the number of attributes provided - `:at_most` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At most this many must be absent. Defaults to the number of attributes provided - `:exactly` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Exactly this many must be absent ## [](Ash.Resource.Validation.Builtins.html#absent/2-examples)Examples ``` validate absent(:unsettable_option) validate absent([:first_name, :last_name]), where: [present(:full_name)] validate absent([:is_admin, :is_normal_user], at_least: 1) ``` [](Ash.Resource.Validation.Builtins.html#action_is/1) # action\_is(action) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L84) ``` @spec action_is(action :: atom()) :: Ash.Resource.Validation.ref() ``` Validates that the action is a specific action. Primarily meant for use in `where`. ## [](Ash.Resource.Validation.Builtins.html#action_is/1-examples)Examples ``` validate present(:foo), where: [action_is(:bar)] ``` [](Ash.Resource.Validation.Builtins.html#argument_does_not_equal/2) # argument\_does\_not\_equal(argument, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L336) ``` @spec argument_does_not_equal(argument :: atom(), value :: term()) :: Ash.Resource.Validation.ref() ``` Validates that an argument is not being changed to a specific value, or does not equal the given value if it is not being changed. ## [](Ash.Resource.Validation.Builtins.html#argument_does_not_equal/2-examples)Examples ``` validate argument_does_not_equal(:admin, true) # Or to only check for changing to a given value validate argument_does_not_equal(:admin, true), where: [changing(:admin)] ``` [](Ash.Resource.Validation.Builtins.html#argument_equals/2) # argument\_equals(argument, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L351) ``` @spec argument_equals(argument :: atom(), value :: term()) :: Ash.Resource.Validation.ref() ``` Validates that an argument is being changed to a specific value, or equals the given value if it is not being changed. ## [](Ash.Resource.Validation.Builtins.html#argument_equals/2-examples)Examples ``` validate argument_equals(:admin, true) # Or to only check for changing to a given value validate argument_equals(:admin, true), where: [changing(:admin)] ``` [](Ash.Resource.Validation.Builtins.html#argument_in/2) # argument\_in(argument, list) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L366) ``` @spec argument_in(argument :: atom(), list :: [term()]) :: Ash.Resource.Validation.ref() ``` Validates that an argument is being changed to one of a set of specific values, or is in the the given list if it is not being changed. ## [](Ash.Resource.Validation.Builtins.html#argument_in/2-examples)Examples ``` validate argument_in(:state, [1, 2, 3]) # Or to only check for changing to a something in a given list validate argument_in(:state, [1, 2, 3]), where: [changing(:state)] ``` [](Ash.Resource.Validation.Builtins.html#attribute_does_not_equal/2) # attribute\_does\_not\_equal(attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L60) ``` @spec attribute_does_not_equal(attribute :: atom(), value :: term()) :: Ash.Resource.Validation.ref() ``` Validates that an attribute is not being changed to a specific value, or does not equal the given value if it is not being changed. ## [](Ash.Resource.Validation.Builtins.html#attribute_does_not_equal/2-examples)Examples ``` validate attribute_does_not_equal(:admin, true) # Or to only check for changing to a given value validate attribute_does_not_equal(:admin, true), where: [changing(:admin)] ``` [](Ash.Resource.Validation.Builtins.html#attribute_equals/2) # attribute\_equals(attribute, value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L99) ``` @spec attribute_equals(attribute :: atom(), value :: term()) :: Ash.Resource.Validation.ref() ``` Validates that an attribute is being changed to a specific value, or equals the given value if it is not being changed. ## [](Ash.Resource.Validation.Builtins.html#attribute_equals/2-examples)Examples ``` validate attribute_equals(:admin, true) # Or to only check for changing to a given value validate attribute_equals(:admin, true), where: [changing(:admin)] ``` [](Ash.Resource.Validation.Builtins.html#attribute_in/2) # attribute\_in(attribute, list) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L114) ``` @spec attribute_in(attribute :: atom(), list :: [term()]) :: Ash.Resource.Validation.ref() ``` Validates that an attribute is being changed to one of a set of specific values, or is in the the given list if it is not being changed. ## [](Ash.Resource.Validation.Builtins.html#attribute_in/2-examples)Examples ``` validate attribute_in(:state, [1, 2, 3]) # Or to only check for changing to a something in a given list validate attribute_in(:state, [1, 2, 3]), where: [changing(:state)] ``` [](Ash.Resource.Validation.Builtins.html#attributes_absent/2) # attributes\_absent(attributes, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L296) ``` @spec attributes_absent(attributes :: atom() | [atom()], opts :: Keyword.t()) :: Ash.Resource.Validation.ref() ``` Validates that the attribute or list of attributes are `nil`. See [`absent/2`](Ash.Resource.Validation.Builtins.html#absent/2) for more information. ## [](Ash.Resource.Validation.Builtins.html#attributes_absent/2-options)Options - `:at_least` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At least this many must be absent. Defaults to the number of attributes provided - `:at_most` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At most this many must be absent. Defaults to the number of attributes provided - `:exactly` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Exactly this many must be absent [](Ash.Resource.Validation.Builtins.html#attributes_present/2) # attributes\_present(attributes, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L222) ``` @spec attributes_present(attributes :: atom() | [atom()], opts :: Keyword.t()) :: Ash.Resource.Validation.ref() ``` Validates that the attribute or list of attributes are not `nil`. See [`present/2`](Ash.Resource.Validation.Builtins.html#present/2) for more information. ## [](Ash.Resource.Validation.Builtins.html#attributes_present/2-options)Options - `:at_least` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At least this many must be present. Defaults to the number of attributes provided - `:at_most` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At most this many must be present. Defaults to the number of attributes provided - `:exactly` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Exactly this many must be present [](Ash.Resource.Validation.Builtins.html#changing/1) # changing(field) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L31) ``` @spec changing(attribute_or_relationship :: atom()) :: Ash.Resource.Validation.ref() ``` Validates that an attribute or relationship is being changed ## [](Ash.Resource.Validation.Builtins.html#changing/1-examples)Examples ``` validate changing(:first_name) validate changing(:comments) ``` [](Ash.Resource.Validation.Builtins.html#compare/2) # compare(attribute, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L160) ``` @spec compare(attribute :: atom(), opts :: Keyword.t()) :: Ash.Resource.Validation.ref() ``` Validates that an attribute or argument meets the given comparison criteria. The values provided for each option may be a literal value, attribute, argument, or a zero argument function. ## [](Ash.Resource.Validation.Builtins.html#compare/2-options)Options - `:greater_than` - The value that the attribute should be greater than. - `:greater_than_or_equal_to` - The value that the attribute should be greater than or equal to - `:less_than` - The value that the attribute should be less than - `:less_than_or_equal_to` - The value that the attribute should be less than or equal to ## [](Ash.Resource.Validation.Builtins.html#compare/2-examples)Examples ``` validate compare(:age, greater_than_or_equal_to: 18), where: [attribute_equals(:show_adult_content, true)], message: "must be over %{greater_than_or_equal_to} to enable adult content." validate compare(:points, greater_than: 0, less_than_or_equal_to: 100) ``` [](Ash.Resource.Validation.Builtins.html#confirm/2) # confirm(field, confirmation) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L45) ``` @spec confirm( attribute_or_argument :: atom(), confirmation_attribute_or_argument :: atom() ) :: Ash.Resource.Validation.ref() ``` Validates that a field or argument matches another field or argument ## [](Ash.Resource.Validation.Builtins.html#confirm/2-examples)Examples ``` validate confirm(:password, :password_confirmation) validate confirm(:email, :email_confirmation) ``` [](Ash.Resource.Validation.Builtins.html#match/2) # match(attribute, match) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L174) ``` @spec match(attribute :: atom(), match :: Regex.t()) :: Ash.Resource.Validation.ref() ``` Validates that an attribute's value matches a given regex. [`String.match?/2`](../elixir/String.html#match?/2) is used to determine if the value matches. ## [](Ash.Resource.Validation.Builtins.html#match/2-examples)Examples ``` validate match(:slug, ~r/^[0-9a-z-_]+$/) ``` [](Ash.Resource.Validation.Builtins.html#negate/1) # negate(validation) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L72) ``` @spec negate(validation :: Ash.Resource.Validation.ref()) :: Ash.Resource.Validation.ref() ``` Validates that other validation does not pass ## [](Ash.Resource.Validation.Builtins.html#negate/1-examples)Examples ``` validate negate(one_of(:status, [:closed, :finished])) ``` [](Ash.Resource.Validation.Builtins.html#numericality/2) # numericality(attribute, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L154) ``` @spec numericality(attribute :: atom(), opts :: Keyword.t()) :: Ash.Resource.Validation.ref() ``` Validates that an attribute or argument meets the given comparison criteria. The values provided for each option may be a literal value, attribute, argument, or a zero argument function. ## [](Ash.Resource.Validation.Builtins.html#numericality/2-options)Options - `:greater_than` - The value that the attribute should be greater than. - `:greater_than_or_equal_to` - The value that the attribute should be greater than or equal to - `:less_than` - The value that the attribute should be less than - `:less_than_or_equal_to` - The value that the attribute should be less than or equal to ## [](Ash.Resource.Validation.Builtins.html#numericality/2-examples)Examples ``` validate numericality(:age, greater_than_or_equal_to: 18), where: [attribute_equals(:show_adult_content, true)], message: "must be over %{greater_than_or_equal_to} to enable adult content." validate numericality(:points, greater_than: 0, less_than_or_equal_to: 100) ``` [](Ash.Resource.Validation.Builtins.html#one_of/2) # one\_of(attribute, values) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L18) ``` @spec one_of(attribute :: atom(), [any()]) :: Ash.Resource.Validation.ref() ``` Validates that an attribute's value is in a given list ## [](Ash.Resource.Validation.Builtins.html#one_of/2-examples)Examples ``` validate one_of(:status, [:closed_won, :closed_lost]) ``` [](Ash.Resource.Validation.Builtins.html#present/2) # present(attributes, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L203) ``` @spec present(attributes_or_arguments :: atom() | [atom()], opts :: Keyword.t()) :: Ash.Resource.Validation.ref() ``` Validates that the given attribute or argument or list of attributes or arguments are not `nil`. Use options to specify how many must not be `nil`. If no options are provided, validates that they are all present. Keep in mind that some types cast certain values to `nil`, and validations are applied after all inputs have been cast. For example, a `:string` type attribute with the default constraints will cast `""` as `nil`, meaning an input of `""` would fail the `present` validation. ## [](Ash.Resource.Validation.Builtins.html#present/2-options)Options - `:at_least` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At least this many must be present. Defaults to the number of attributes provided - `:at_most` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - At most this many must be present. Defaults to the number of attributes provided - `:exactly` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Exactly this many must be present ## [](Ash.Resource.Validation.Builtins.html#present/2-examples)Examples ``` validate present(:name) validate present([:first_name, :last_name]), where: [absent(:full_name)] validate present([:is_admin, :is_normal_user], at_most: 1) ``` [](Ash.Resource.Validation.Builtins.html#string_length/2) # string\_length(attribute, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation/builtins.ex#L132) ``` @spec string_length(attribute :: atom(), opts :: Keyword.t()) :: Ash.Resource.Validation.ref() ``` Validates that an attribute on the original record meets the given length criteria ## [](Ash.Resource.Validation.Builtins.html#string_length/2-options)Options - `:min` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - String must be this length at least - `:max` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - String must be this length at most - `:exact` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - String must be this length exactly ## [](Ash.Resource.Validation.Builtins.html#string_length/2-examples)Examples ``` validate string_length(:slug, exact: 8) validate string_length(:password, min: 6) validate string_length(:secret, min: 4, max: 12) ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Validation.Context (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L44 "View Source") Context for a validation. # [](Ash.Resource.Validation.Context.html#summary)Summary ## [Types](Ash.Resource.Validation.Context.html#types) [t()](Ash.Resource.Validation.Context.html#t:t/0) # [](Ash.Resource.Validation.Context.html#types)Types [](Ash.Resource.Validation.Context.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L50) ``` @type t() :: %Ash.Resource.Validation.Context{ actor: Ash.Resource.record() | nil, authorize?: boolean() | nil, bulk?: boolean(), message: String.t() | nil, tenant: term(), tracer: Ash.Tracer.t() | [Ash.Tracer.t()] | nil } ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Validation behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L1 "View Source") Represents a validation in Ash. See [`Ash.Resource.Validation.Builtins`](Ash.Resource.Validation.Builtins.html) for a list of builtin validations. To write your own validation, define a module that implements the [`init/1`](Ash.Resource.Validation.html#c:init/1) callback to validate options at compile time, and [`validate/3`](Ash.Resource.Validation.html#c:validate/3) callback to do the validation. Then, in a resource, you can say: ``` validations do validate {MyValidation, [foo: :bar]} end ``` # [](Ash.Resource.Validation.html#summary)Summary ## [Types](Ash.Resource.Validation.html#types) [path()](Ash.Resource.Validation.html#t:path/0) [ref()](Ash.Resource.Validation.html#t:ref/0) [t()](Ash.Resource.Validation.html#t:t/0) ## [Callbacks](Ash.Resource.Validation.html#callbacks) [atomic(changeset, opts, context)](Ash.Resource.Validation.html#c:atomic/3) [atomic?()](Ash.Resource.Validation.html#c:atomic?/0) [describe(opts)](Ash.Resource.Validation.html#c:describe/1) [has\_validate?()](Ash.Resource.Validation.html#c:has_validate?/0) [init(opts)](Ash.Resource.Validation.html#c:init/1) [validate(changeset, opts, context)](Ash.Resource.Validation.html#c:validate/3) ## [Functions](Ash.Resource.Validation.html#functions) [action\_schema()](Ash.Resource.Validation.html#action_schema/0) [opt\_schema()](Ash.Resource.Validation.html#opt_schema/0) [validation\_type()](Ash.Resource.Validation.html#validation_type/0) # [](Ash.Resource.Validation.html#types)Types [](Ash.Resource.Validation.html#t:path/0) # path() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L41) ``` @type path() :: [atom() | integer()] ``` [](Ash.Resource.Validation.html#t:ref/0) # ref() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L42) ``` @type ref() :: {module(), Keyword.t()} | module() ``` [](Ash.Resource.Validation.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L31) ``` @type t() :: %Ash.Resource.Validation{ always_atomic?: term(), before_action?: term(), description: String.t() | nil, message: term(), module: atom(), on: [atom()], only_when_valid?: boolean(), opts: [atom()], validation: {atom(), [atom()]}, where: [{atom(), [atom()]}] } ``` # [](Ash.Resource.Validation.html#callbacks)Callbacks [](Ash.Resource.Validation.html#c:atomic/3) # atomic(changeset, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L65) ``` @callback atomic( changeset :: Ash.Changeset.t(), opts :: Keyword.t(), context :: Ash.Resource.Validation.Context.t() ) :: :ok | {:atomic, involved_fields :: [atom()] | :*, condition_expr :: Ash.Expr.t(), error_expr :: Ash.Expr.t()} | [ {:atomic, involved_fields :: [atom()] | :*, condition_expr :: Ash.Expr.t(), error_expr :: Ash.Expr.t()} ] | {:not_atomic, String.t()} | {:error, term()} ``` [](Ash.Resource.Validation.html#c:atomic?/0) # atomic?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L76) ``` @callback atomic?() :: boolean() ``` [](Ash.Resource.Validation.html#c:describe/1) # describe(opts) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L63) ``` @callback describe(opts :: Keyword.t()) :: String.t() | [message: String.t(), vars: Keyword.t()] ``` [](Ash.Resource.Validation.html#c:has_validate?/0) # has\_validate?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L77) ``` @callback has_validate?() :: boolean() ``` [](Ash.Resource.Validation.html#c:init/1) # init(opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L60) ``` @callback init(opts :: Keyword.t()) :: {:ok, Keyword.t()} | {:error, String.t()} ``` [](Ash.Resource.Validation.html#c:validate/3) # validate(changeset, opts, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L61) ``` @callback validate( changeset :: Ash.Changeset.t(), opts :: Keyword.t(), context :: Ash.Resource.Validation.Context.t() ) :: :ok | {:error, term()} ``` # [](Ash.Resource.Validation.html#functions)Functions [](Ash.Resource.Validation.html#action_schema/0) # action\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L199) [](Ash.Resource.Validation.html#opt_schema/0) # opt\_schema() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L198) [](Ash.Resource.Validation.html#validation_type/0) # validation\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/validation.ex#L200) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/ensure_aggregate_field_is_attribute_or_calculation.ex#L1 "View Source") Ensures that the field at the end of the path is an attribute or calculation. # [](Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation.html#functions) [verify(dsl)](Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation.html#functions)Functions [](Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/ensure_aggregate_field_is_attribute_or_calculation.ex#L7) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.NoReservedFieldNames (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/no_reserved_field_names.ex#L1 "View Source") Confirms that a resource does not use reserved names for field names. Reserved field names are: \[:**struct**, :**meta**, :**metadata**, :**order**, :**lateral\_join\_source**, :\*, :calculations, :aggregates, :relationships, :as]. # [](Ash.Resource.Verifiers.NoReservedFieldNames.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.NoReservedFieldNames.html#functions) [verify(dsl\_state)](Ash.Resource.Verifiers.NoReservedFieldNames.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.NoReservedFieldNames.html#functions)Functions [](Ash.Resource.Verifiers.NoReservedFieldNames.html#verify/1) # verify(dsl\_state) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/no_reserved_field_names.ex#L12) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateAccept (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_accept.ex#L1 "View Source") Validates that accept and reject lists only contain valid attributes [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateActionTypesSupported (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_action_types_supported.ex#L1 "View Source") Confirms that all action types declared on a resource are supported by its data layer [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateAggregatesSupported (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_aggregates_supported.ex#L1 "View Source") Confirms that all aggregates are supported by the data layer [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_arguments_to_code_interface.ex#L1 "View Source") Validate the arguments defined in the code interface and reject arguments that are not action attributes/arguments # [](Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface.html#functions) [verify\_interface!(interface, action, attributes, module)](Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface.html#verify_interface!/4) # [](Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface.html#functions)Functions [](Ash.Resource.Verifiers.ValidateArgumentsToCodeInterface.html#verify_interface!/4) # verify\_interface!(interface, action, attributes, module) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_arguments_to_code_interface.ex#L28) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateEagerIdentities (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_eager_identities.ex#L1 "View Source") Confirms that eager identities are not declared on a resource with no primary read. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateManagedRelationshipOpts (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_manage_relationship_opts.ex#L1 "View Source") Confirms that all action types declared on a resource are supported by its data layer [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateMultitenancy (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_multitenancy.ex#L1 "View Source") Ensures that the multitenancy configuration is valid for the given resource [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidatePrimaryKey (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_primary_key.ex#L1 "View Source") Validates and caches the primary key of a resource [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateRelationshipAttributes (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_relationship_attributes.ex#L1 "View Source") Validates that all relationships point to valid fields [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_relationship_attributes_match.ex#L1 "View Source") Shows a warning on potentially incompatible relationship attributes. # [](Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch.html#functions) [verify(dsl)](Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch.html#functions)Functions [](Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/validate_relationship_attributes_match.ex#L7) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.VerifyActionsAtomic (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_actions_atomic.ex#L1 "View Source") Raises an error on update or destroy actions with `require_atomic?` set to true when it is known at compile time that they will not be atomic. # [](Ash.Resource.Verifiers.VerifyActionsAtomic.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.VerifyActionsAtomic.html#functions) [verify(dsl)](Ash.Resource.Verifiers.VerifyActionsAtomic.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.VerifyActionsAtomic.html#functions)Functions [](Ash.Resource.Verifiers.VerifyActionsAtomic.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_actions_atomic.ex#L8) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.VerifyGenericActionReactorInputs (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_generic_action_reactor_inputs.ex#L1 "View Source") Returns an error if a generic action calls a Reactor module without specifying an argument for all expected inputs. # [](Ash.Resource.Verifiers.VerifyGenericActionReactorInputs.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.VerifyGenericActionReactorInputs.html#functions) [verify(dsl)](Ash.Resource.Verifiers.VerifyGenericActionReactorInputs.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.VerifyGenericActionReactorInputs.html#functions)Functions [](Ash.Resource.Verifiers.VerifyGenericActionReactorInputs.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_generic_action_reactor_inputs.ex#L8) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.VerifyIdentityFields (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_identities.ex#L1 "View Source") Raises an error on potentially incompatible identity attributes. # [](Ash.Resource.Verifiers.VerifyIdentityFields.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.VerifyIdentityFields.html#functions) [verify(dsl)](Ash.Resource.Verifiers.VerifyIdentityFields.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.VerifyIdentityFields.html#functions)Functions [](Ash.Resource.Verifiers.VerifyIdentityFields.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_identities.ex#L7) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.VerifyPrimaryKeyPresent (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_primary_key_present.ex#L1 "View Source") Raises an error when a required primary key is missing # [](Ash.Resource.Verifiers.VerifyPrimaryKeyPresent.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.VerifyPrimaryKeyPresent.html#functions) [verify(dsl)](Ash.Resource.Verifiers.VerifyPrimaryKeyPresent.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.VerifyPrimaryKeyPresent.html#functions)Functions [](Ash.Resource.Verifiers.VerifyPrimaryKeyPresent.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_primary_key_present.ex#L8) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.VerifyReservedCalculationArguments (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_reserved_calculation_arguments.ex#L1 "View Source") Verifies that standard context keys are not used as calculation arguments # [](Ash.Resource.Verifiers.VerifyReservedCalculationArguments.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.VerifyReservedCalculationArguments.html#functions) [verify(dsl)](Ash.Resource.Verifiers.VerifyReservedCalculationArguments.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.VerifyReservedCalculationArguments.html#functions)Functions [](Ash.Resource.Verifiers.VerifyReservedCalculationArguments.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_reserved_calculation_arguments.ex#L7) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource.Verifiers.VerifySelectedByDefault (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_selected_by_default.ex#L1 "View Source") Raises an error when a required primary key is missing # [](Ash.Resource.Verifiers.VerifySelectedByDefault.html#summary)Summary ## [Functions](Ash.Resource.Verifiers.VerifySelectedByDefault.html#functions) [verify(dsl)](Ash.Resource.Verifiers.VerifySelectedByDefault.html#verify/1) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). # [](Ash.Resource.Verifiers.VerifySelectedByDefault.html#functions)Functions [](Ash.Resource.Verifiers.VerifySelectedByDefault.html#verify/1) # verify(dsl) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/resource/verifiers/verify_selected_by_default.ex#L8) Callback implementation for [`Spark.Dsl.Verifier.verify/1`](../spark/2.2.40/Spark.Dsl.Verifier.html#c:verify/1). [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.SatSolver (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L1 "View Source") Tools for working with the satsolver that drives filter subset checking (for authorization) This is public as a very low level toolkit for writing authorizers, but you almost certainly do not need to look at this module. If you are looking for information about how authorization works, see the [policy guide](policies.html) # [](Ash.SatSolver.html#summary)Summary ## [Functions](Ash.SatSolver.html#functions) [b(statement)](Ash.SatSolver.html#b/1) Creates tuples of a boolean statement. [left\_excludes\_right(left, right)](Ash.SatSolver.html#left_excludes_right/2) Returns `b(not (left and right))` [left\_implies\_right(left, right)](Ash.SatSolver.html#left_implies_right/2) Returns `b(not (left and not right))` [mutually\_exclusive(predicates, acc \\\\ \[\])](Ash.SatSolver.html#mutually_exclusive/2) Returns a statement expressing that the predicates are mutually exclusive. [mutually\_exclusive\_and\_collectively\_exhaustive(predicates)](Ash.SatSolver.html#mutually_exclusive_and_collectively_exhaustive/1) Returns a statement expressing that the predicates are mutually exclusive and collectively exhaustive. [mutually\_inclusive(predicates, acc \\\\ \[\])](Ash.SatSolver.html#mutually_inclusive/2) Returns a statement expressing that the predicates are mutually inclusive [right\_excludes\_left(left, right)](Ash.SatSolver.html#right_excludes_left/2) Returns `b(not (right and left))` [right\_implies\_left(left, right)](Ash.SatSolver.html#right_implies_left/2) Returns `b(not (right and not left))` [strict\_filter\_subset(filter, candidate)](Ash.SatSolver.html#strict_filter_subset/2) Returns true if the candidate filter returns the same or less data than the filter [synonymous\_relationship\_paths?(left\_resource, candidate, search, right\_resource \\\\ nil)](Ash.SatSolver.html#synonymous_relationship_paths?/4) Returns `true` if the relationship paths are synonymous from a data perspective [to\_cnf(expression)](Ash.SatSolver.html#to_cnf/1) Transforms a statement to Conjunctive Normal Form(CNF), as lists of lists of integers. [transform(resource, expression)](Ash.SatSolver.html#transform/2) Prepares a filter for comparison [transform\_and\_solve(resource, expression)](Ash.SatSolver.html#transform_and_solve/2) Calls [`transform/2`](Ash.SatSolver.html#transform/2) and solves the expression # [](Ash.SatSolver.html#functions)Functions [](Ash.SatSolver.html#b/1) # b(statement) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L27) Creates tuples of a boolean statement. i.e `b(1 and 2) #=> {:and, 1, 2}` [](Ash.SatSolver.html#left_excludes_right/2) # left\_excludes\_right(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L275) ``` @spec left_excludes_right(Ash.Expr.t(), Ash.Expr.t()) :: boolean_expr() ``` Returns `b(not (left and right))` [](Ash.SatSolver.html#left_implies_right/2) # left\_implies\_right(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L306) Returns `b(not (left and not right))` [](Ash.SatSolver.html#mutually_exclusive/2) # mutually\_exclusive(predicates, acc \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L234) Returns a statement expressing that the predicates are mutually exclusive. [](Ash.SatSolver.html#mutually_exclusive_and_collectively_exhaustive/1) # mutually\_exclusive\_and\_collectively\_exhaustive(predicates) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L248) ``` @spec mutually_exclusive_and_collectively_exhaustive([Ash.Expr.t()]) :: boolean_expr() ``` Returns a statement expressing that the predicates are mutually exclusive and collectively exhaustive. [](Ash.SatSolver.html#mutually_inclusive/2) # mutually\_inclusive(predicates, acc \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L287) Returns a statement expressing that the predicates are mutually inclusive [](Ash.SatSolver.html#right_excludes_left/2) # right\_excludes\_left(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L281) ``` @spec right_excludes_left(Ash.Expr.t(), Ash.Expr.t()) :: boolean_expr() ``` Returns `b(not (right and left))` [](Ash.SatSolver.html#right_implies_left/2) # right\_implies\_left(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L301) ``` @spec right_implies_left(Ash.Expr.t(), Ash.Expr.t()) :: boolean_expr() ``` Returns `b(not (right and not left))` [](Ash.SatSolver.html#strict_filter_subset/2) # strict\_filter\_subset(filter, candidate) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L60) ``` @spec strict_filter_subset(Ash.Filter.t(), Ash.Filter.t()) :: boolean() | :maybe ``` Returns true if the candidate filter returns the same or less data than the filter [](Ash.SatSolver.html#synonymous_relationship_paths?/4) # synonymous\_relationship\_paths?(left\_resource, candidate, search, right\_resource \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L122) ``` @spec synonymous_relationship_paths?( Ash.Resource.t(), [atom()], [atom()], Ash.Resource.t() ) :: boolean() ``` Returns `true` if the relationship paths are synonymous from a data perspective [](Ash.SatSolver.html#to_cnf/1) # to\_cnf(expression) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L355) Transforms a statement to Conjunctive Normal Form(CNF), as lists of lists of integers. [](Ash.SatSolver.html#transform/2) # transform(resource, expression) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L78) ``` @spec transform(Ash.Resource.t(), Ash.Expr.t()) :: boolean_expr() ``` Prepares a filter for comparison [](Ash.SatSolver.html#transform_and_solve/2) # transform\_and\_solve(resource, expression) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/sat_solver/sat_solver.ex#L88) ``` @spec transform_and_solve(Ash.Resource.t(), Ash.Expr.t()) :: {:ok, [integer()]} | {:error, :unsatisfiable} ``` Calls [`transform/2`](Ash.SatSolver.html#transform/2) and solves the expression [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Seed (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/seed.ex#L1 "View Source") Helpers for seeding data, useful for quickly creating lots of data either for database seeding or testing. Important: this bypasses resource actions, and goes straight to the data layer. No action changes or validations are run. The only thing that it does at the moment is ensure that default values for attributes are set, it does not validate that required attributes are set (although the data layer may do that for you, e.g with ash\_postgres). # [](Ash.Seed.html#summary)Summary ## [Functions](Ash.Seed.html#functions) [keep\_nil()](Ash.Seed.html#keep_nil/0) Returns `:__keep_nil__`, allowing to ensure a default value is not used when you want the value to be `nil`. [seed!(input)](Ash.Seed.html#seed!/1) Seed using a record (instance of a resource) as input. [seed!(resource, input, opts \\\\ \[\])](Ash.Seed.html#seed!/3) Performs a direct call to the data layer of a resource with the provided input. [update!(record, input)](Ash.Seed.html#update!/2) [upsert!(input, opts \\\\ \[\])](Ash.Seed.html#upsert!/2) Performs an upsert operation on the data layer of a resource with the provided input and identities. The usage is the same as [`seed!/1`](Ash.Seed.html#seed!/1), but it will update the record if it already exists. [upsert!(resource, input, opts)](Ash.Seed.html#upsert!/3) Usage is the same as [`seed!/2`](Ash.Seed.html#seed!/2), but it will update the record if it already exists based on the identities. # [](Ash.Seed.html#functions)Functions [](Ash.Seed.html#keep_nil/0) # keep\_nil() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/seed.ex#L299) Returns `:__keep_nil__`, allowing to ensure a default value is not used when you want the value to be `nil`. [](Ash.Seed.html#seed!/1) # seed!(input) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/seed.ex#L25) Seed using a record (instance of a resource) as input. If the passed in struct was retrieved from the data layer already (i.e already seeded), then it is returned and nothing is done. Otherwise, the attributes and relationships are used as input to `seed/2`, after having any `%Ash.NotLoaded{}` values stripped out. Any `nil` values will be overwritten with their default values. To avoid this, either use `seed/2` in which providing the key will have it not set the default values. If you want to force `nil` to be accepted and prevent the default value from being set, use the [`keep_nil/0`](Ash.Seed.html#keep_nil/0) function provided here, which returns `:__keep_nil__`. Alternatively, use `seed!(Post, %{text: nil})`. See [`seed!/2`](Ash.Seed.html#seed!/2) for more information. [](Ash.Seed.html#seed!/3) # seed!(resource, input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/seed.ex#L67) Performs a direct call to the data layer of a resource with the provided input. If a list is provided as input, then you will get back that many results. To set a tenant, use the tenant option. [](Ash.Seed.html#update!/2) # update!(record, input) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/seed.ex#L280) [](Ash.Seed.html#upsert!/2) # upsert!(input, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/seed.ex#L154) Performs an upsert operation on the data layer of a resource with the provided input and identities. The usage is the same as [`seed!/1`](Ash.Seed.html#seed!/1), but it will update the record if it already exists. ``` Ash.Seed.upsert!(%User{email: 'test@gmail.com', name: 'Test'}, identity: :email) ``` [](Ash.Seed.html#upsert!/3) # upsert!(resource, input, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/seed.ex#L201) Usage is the same as [`seed!/2`](Ash.Seed.html#seed!/2), but it will update the record if it already exists based on the identities. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Sort (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L1 "View Source") Utilities and types for sorting. # [](Ash.Sort.html#summary)Summary ## [Types](Ash.Sort.html#types) [sort\_item()](Ash.Sort.html#t:sort_item/0) [sort\_order()](Ash.Sort.html#t:sort_order/0) [t()](Ash.Sort.html#t:t/0) ## [Functions](Ash.Sort.html#functions) [expr\_sort(expression, type \\\\ nil)](Ash.Sort.html#expr_sort/2) Builds an expression to be used in a sort statement. [parse\_input(resource, sort, handler \\\\ nil)](Ash.Sort.html#parse_input/3) A utility for parsing sorts provided from external input. Only allows sorting on public fields. [parse\_input!(resource, sort, handler \\\\ nil)](Ash.Sort.html#parse_input!/3) Same as [`parse_input/2`](Ash.Sort.html#parse_input/2) except raises any errors [parse\_sort(resource, sort, handler \\\\ nil)](Ash.Sort.html#parse_sort/3) [reverse(sort)](Ash.Sort.html#reverse/1) Reverses an Ash sort statement. [runtime\_sort(results, sort, domain \\\\ nil)](Ash.Sort.html#runtime_sort/3) A utility for sorting a list of records at runtime. # [](Ash.Sort.html#types)Types [](Ash.Sort.html#t:sort_item/0) # sort\_item() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L9) ``` @type sort_item() :: atom() | {atom(), sort_order()} | %Ash.Query.Calculation{ async?: term(), calc_name: term(), constraints: term(), context: term(), filterable?: term(), load: term(), module: term(), name: term(), opts: term(), required_loads: term(), select: term(), sensitive?: term(), sortable?: term(), type: term() } | {%Ash.Query.Calculation{ async?: term(), calc_name: term(), constraints: term(), context: term(), filterable?: term(), load: term(), module: term(), name: term(), opts: term(), required_loads: term(), select: term(), sensitive?: term(), sortable?: term(), type: term() }, sort_order()} | {atom(), {Keyword.t() | map(), sort_order()}} ``` [](Ash.Sort.html#t:sort_order/0) # sort\_order() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L6) ``` @type sort_order() :: :asc | :desc | :asc_nils_first | :asc_nils_last | :desc_nils_first | :desc_nils_last ``` [](Ash.Sort.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L16) ``` @type t() :: [sort_item()] | sort_item() ``` # [](Ash.Sort.html#functions)Functions [](Ash.Sort.html#expr_sort/2) # expr\_sort(expression, type \\\\ nil) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L34) ``` @spec expr_sort(Ash.Expr.t(), Ash.Type.t() | nil) :: Ash.Expr.t() ``` Builds an expression to be used in a sort statement. For example: ``` Ash.Query.sort(query, Ash.Sort.expr_sort(author.full_name, :string)) Ash.Query.sort(query, [{Ash.Sort.expr_sort(author.full_name, :string), :desc_nils_first}]) ``` [](Ash.Sort.html#parse_input/3) # parse\_input(resource, sort, handler \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L119) ``` @spec parse_input( Ash.Resource.t(), String.t() | [atom() | String.t() | {atom(), sort_order()} | [String.t()]] | nil, nil | (String.t() -> nil | atom() | {atom(), map()}) ) :: {:ok, t()} | {:error, term()} ``` A utility for parsing sorts provided from external input. Only allows sorting on public fields. The supported formats are: ### [](Ash.Sort.html#parse_input/3-sort-strings)Sort Strings A comma separated list of fields to sort on, each with an optional prefix. The prefixes are: - "+" - Same as no prefix. Sorts `:asc`. - "++" - Sorts `:asc_nils_first` - "-" - Sorts `:desc` - "--" - Sorts `:desc_nils_last` For example ``` "foo,-bar,++baz,--buz" ``` ### [](Ash.Sort.html#parse_input/3-a-list-of-sort-strings)A list of sort strings Same prefix rules as above, but provided as a list. For example: ``` ["foo", "-bar", "++baz", "--buz"] ``` ## [](Ash.Sort.html#parse_input/3-handling-specific-values)Handling specific values A handler function may be provided that takes a string, and returns the relevant sort It won't be given any prefixes, only the field. This allows for things like parsing the calculation values out of the sort, or setting calculation values if they are not included in the sort string. To return calculation parameters, return `{:field, %{param: :value}}`. This will end up as something like `{:field, {%{param: :value}, :desc}}`, with the corresponding sort order. This handler function will only be called if you pass in a string or list of strings for the sort. Atoms will be assumed to have already been handled. The handler should return `nil` if it is not handling the given field. [](Ash.Sort.html#parse_input!/3) # parse\_input!(resource, sort, handler \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L149) Same as [`parse_input/2`](Ash.Sort.html#parse_input/2) except raises any errors See [`parse_input/2`](Ash.Sort.html#parse_input/2) for more. [](Ash.Sort.html#parse_sort/3) # parse\_sort(resource, sort, handler \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L159) [](Ash.Sort.html#reverse/1) # reverse(sort) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L310) Reverses an Ash sort statement. [](Ash.Sort.html#runtime_sort/3) # runtime\_sort(results, sort, domain \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/sort/sort.ex#L346) A utility for sorting a list of records at runtime. For example: ``` Ash.Sort.runtime_sort([record1, record2, record3], name: :asc, type: :desc_nils_last) ``` Keep in mind that it is unrealistic to expect this runtime sort to always be exactly the same as a sort that may have been applied by your data layer. This is especially true for strings. For example, `Postgres` strings have a collation that affects their sorting, making it unpredictable from the perspective of a tool using the database: [https://www.postgresql.org/docs/current/collation.html](https://www.postgresql.org/docs/current/collation.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Test (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/test.ex#L1 "View Source") Testing helpers for Ash. # [](Ash.Test.html#summary)Summary ## [Functions](Ash.Test.html#functions) [assert\_has\_error(changeset\_query\_or\_input, error\_class \\\\ nil, callback, opts \\\\ \[\])](Ash.Test.html#assert_has_error/4) Assert that the given changeset, query, or action input has a matching error. [refute\_has\_error(changeset\_query\_or\_input, error\_class \\\\ nil, callback, opts \\\\ \[\])](Ash.Test.html#refute_has_error/4) Refute that the given changeset, query, or action input has a matching error. [strip\_metadata(structs)](Ash.Test.html#strip_metadata/1) Clears the `__metadata__` field and the underlying ecto `__meta__` field # [](Ash.Test.html#functions)Functions [](Ash.Test.html#assert_has_error/4) # assert\_has\_error(changeset\_query\_or\_input, error\_class \\\\ nil, callback, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/test.ex#L23) Assert that the given changeset, query, or action input has a matching error. Use the optional second argument to assert that the errors (all together) are of a specific class. [](Ash.Test.html#refute_has_error/4) # refute\_has\_error(changeset\_query\_or\_input, error\_class \\\\ nil, callback, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/test.ex#L115) Refute that the given changeset, query, or action input has a matching error. The `error_class` argument has been deprecated and should not be used. [](Ash.Test.html#strip_metadata/1) # strip\_metadata(structs) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/test.ex#L176) Clears the `__metadata__` field and the underlying ecto `__meta__` field This allows for easier comparison of changeset/query results [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.ToTenant protocol (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/to_tenant.ex#L1 "View Source") Converts a value to a tenant. To add this to a resource, implement the protocol like so:application What this should do is entirely dependent on how you've set up your tenants. This example assumes that you want the tenant to be `org_#{organization_id}`, but it could also be something like `organization.schema`. ``` defmodule MyApp.Organization do use Ash.Resource, ... ... defimpl Ash.ToTenant do def to_tenant(%{id: id}, _resource), do: "org_#{id}" end end ``` # [](Ash.ToTenant.html#summary)Summary ## [Types](Ash.ToTenant.html#types) [t()](Ash.ToTenant.html#t:t/0) ## [Functions](Ash.ToTenant.html#functions) [to\_tenant(value, resource)](Ash.ToTenant.html#to_tenant/2) # [](Ash.ToTenant.html#types)Types [](Ash.ToTenant.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/to_tenant.ex#L22) ``` @type t() :: term() ``` # [](Ash.ToTenant.html#functions)Functions [](Ash.ToTenant.html#to_tenant/2) # to\_tenant(value, resource) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/to_tenant.ex#L25) ``` @spec to_tenant(t(), Ash.Resource.t()) :: term() ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Tracer behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L1 "View Source") A behaviour for implementing tracing for an Ash application. # [](Ash.Tracer.html#summary)Summary ## [Types](Ash.Tracer.html#types) [metadata()](Ash.Tracer.html#t:metadata/0) [span\_type()](Ash.Tracer.html#t:span_type/0) [t()](Ash.Tracer.html#t:t/0) ## [Callbacks](Ash.Tracer.html#callbacks) [get\_span\_context()](Ash.Tracer.html#c:get_span_context/0) [set\_error(t)](Ash.Tracer.html#c:set_error/1) [set\_error(t, t)](Ash.Tracer.html#c:set_error/2) [set\_handled\_error(t, t)](Ash.Tracer.html#c:set_handled_error/2) [set\_metadata(span\_type, metadata)](Ash.Tracer.html#c:set_metadata/2) Set metadata for the current span. [set\_span\_context(term)](Ash.Tracer.html#c:set_span_context/1) [start\_span(span\_type, name)](Ash.Tracer.html#c:start_span/2) [stop\_span()](Ash.Tracer.html#c:stop_span/0) [trace\_type?(atom)](Ash.Tracer.html#c:trace_type?/1) ## [Functions](Ash.Tracer.html#functions) [get\_span\_context(tracer)](Ash.Tracer.html#get_span_context/1) [set\_error(tracers, error)](Ash.Tracer.html#set_error/2) [set\_error(tracers, error, opts)](Ash.Tracer.html#set_error/3) [set\_handled\_error(tracers, error, opts)](Ash.Tracer.html#set_handled_error/3) [set\_metadata(tracers, type, metadata)](Ash.Tracer.html#set_metadata/3) [set\_span\_context(tracer, context)](Ash.Tracer.html#set_span_context/2) [span(type, name, tracer, block\_opts \\\\ \[\])](Ash.Tracer.html#span/4) [start\_span(tracers, type, name)](Ash.Tracer.html#start_span/3) [stop\_span(tracers)](Ash.Tracer.html#stop_span/1) [telemetry\_span(name, metadata, opts \\\\ \[\], block\_opts)](Ash.Tracer.html#telemetry_span/4) [trace\_type?(tracer, type)](Ash.Tracer.html#trace_type?/2) # [](Ash.Tracer.html#types)Types [](Ash.Tracer.html#t:metadata/0) # metadata() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L24) ``` @type metadata() :: %{ domain: nil | module(), resource: nil | module(), actor: term(), tenant: term(), action: atom(), authorize?: boolean() } ``` [](Ash.Tracer.html#t:span_type/0) # span\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L6) ``` @type span_type() :: :action | :changeset | :query | :flow | :calculate | :request_step | :change | :validation | :preparation | :custom_flow_step | :custom | :before_transaction | :before_action | :after_transaction | :after_action | {:custom, atom()} ``` [](Ash.Tracer.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L33) ``` @type t() :: module() ``` # [](Ash.Tracer.html#callbacks)Callbacks [](Ash.Tracer.html#c:get_span_context/0) # get\_span\_context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L37) ``` @callback get_span_context() :: term() ``` [](Ash.Tracer.html#c:set_error/1) # set\_error(t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L49) ``` @callback set_error(Exception.t()) :: :ok ``` [](Ash.Tracer.html#c:set_error/2) # set\_error(t, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L39) ``` @callback set_error(Exception.t(), Keyword.t()) :: :ok ``` [](Ash.Tracer.html#c:set_handled_error/2) # set\_handled\_error(t, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L41) ``` @callback set_handled_error(Exception.t(), Keyword.t()) :: :ok ``` [](Ash.Tracer.html#c:set_metadata/2) # set\_metadata(span\_type, metadata) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L48) ``` @callback set_metadata(span_type(), metadata()) :: :ok ``` Set metadata for the current span. This may be called multiple times per span, and should ideally merge with previous metadata. [](Ash.Tracer.html#c:set_span_context/1) # set\_span\_context(term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L38) ``` @callback set_span_context(term()) :: :ok ``` [](Ash.Tracer.html#c:start_span/2) # start\_span(span\_type, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L35) ``` @callback start_span(span_type(), name :: String.t()) :: :ok ``` [](Ash.Tracer.html#c:stop_span/0) # stop\_span() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L36) ``` @callback stop_span() :: :ok ``` [](Ash.Tracer.html#c:trace_type?/1) # trace\_type?(atom) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L40) ``` @callback trace_type?(atom()) :: boolean() ``` # [](Ash.Tracer.html#functions)Functions [](Ash.Tracer.html#get_span_context/1) # get\_span\_context(tracer) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L199) [](Ash.Tracer.html#set_error/2) # set\_error(tracers, error) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L185) [](Ash.Tracer.html#set_error/3) # set\_error(tracers, error, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L171) [](Ash.Tracer.html#set_handled_error/3) # set\_handled\_error(tracers, error, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L157) [](Ash.Tracer.html#set_metadata/3) # set\_metadata(tracers, type, metadata) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L219) [](Ash.Tracer.html#set_span_context/2) # set\_span\_context(tracer, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L209) [](Ash.Tracer.html#span/4) # span(type, name, tracer, block\_opts \\\\ \[]) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L53) [](Ash.Tracer.html#start_span/3) # start\_span(tracers, type, name) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L145) [](Ash.Tracer.html#stop_span/1) # stop\_span(tracers) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L127) [](Ash.Tracer.html#telemetry_span/4) # telemetry\_span(name, metadata, opts \\\\ \[], block\_opts) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L80) [](Ash.Tracer.html#trace_type?/2) # trace\_type?(tracer, type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/tracer.ex#L137) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Tracer.Simple (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/simple.ex#L1 "View Source") A simple tracer that can send traces to the current process or call a module with the trace. # [](Ash.Tracer.Simple.html#summary)Summary ## [Functions](Ash.Tracer.Simple.html#functions) [gather\_spans()](Ash.Tracer.Simple.html#gather_spans/0) # [](Ash.Tracer.Simple.html#functions)Functions [](Ash.Tracer.Simple.html#gather_spans/0) # gather\_spans() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/simple.ex#L86) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Tracer.Simple.Span (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/tracer/simple.ex#L7 "View Source") A span produced by [`Ash.Tracer.Simple`](Ash.Tracer.Simple.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Atom (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/atom.ex#L1 "View Source") Stores an atom as a string in the database A builtin type that can be referenced via `:atom` ### [](Ash.Type.Atom.html#module-constraints)Constraints - `:one_of` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Allows constraining the value of an atom to a pre-defined list # [](Ash.Type.Atom.html#summary)Summary ## [Functions](Ash.Type.Atom.html#functions) [handle\_change?()](Ash.Type.Atom.html#handle_change?/0) [prepare\_change?()](Ash.Type.Atom.html#prepare_change?/0) # [](Ash.Type.Atom.html#functions)Functions [](Ash.Type.Atom.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/atom.ex#L1) [](Ash.Type.Atom.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/atom.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Binary (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/binary.ex#L1 "View Source") Represents a binary. A builtin type that can be referenced via `:binary` # [](Ash.Type.Binary.html#summary)Summary ## [Functions](Ash.Type.Binary.html#functions) [handle\_change?()](Ash.Type.Binary.html#handle_change?/0) [prepare\_change?()](Ash.Type.Binary.html#prepare_change?/0) # [](Ash.Type.Binary.html#functions)Functions [](Ash.Type.Binary.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/binary.ex#L1) [](Ash.Type.Binary.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/binary.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Boolean (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/boolean.ex#L1 "View Source") Represents a boolean. A builtin type that can be referenced via `:boolean` # [](Ash.Type.Boolean.html#summary)Summary ## [Functions](Ash.Type.Boolean.html#functions) [handle\_change?()](Ash.Type.Boolean.html#handle_change?/0) [prepare\_change?()](Ash.Type.Boolean.html#prepare_change?/0) # [](Ash.Type.Boolean.html#functions)Functions [](Ash.Type.Boolean.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/boolean.ex#L1) [](Ash.Type.Boolean.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/boolean.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.CiString (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/ci_string.ex#L1 "View Source") Stores a case insensitive string in the database See [`Ash.CiString`](Ash.CiString.html) for more information. A builtin type that can be referenced via `:ci_string` ### [](Ash.Type.CiString.html#module-constraints)Constraints - `:max_length` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Enforces a maximum length on the value - `:min_length` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Enforces a minimum length on the value - `:match` - Enforces that the string matches a passed in regex - `:trim?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Trims the value. The default value is `true`. - `:allow_empty?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Sets the value to `nil` if it's empty. The default value is `false`. - `:casing` - Lowercases or uppercases the value, fully discarding case information. For example, if you don't set this, a value of `FrEd` could be saved to the data layer. `FrEd` and `fReD` would still compare as equal, but the original casing information is retained. In many cases, this is what you want. In some cases, however, you want to remove all case information. For example, in an email, you may want to support a user inputting an upper case letter, but discard it when saved. Valid values are :upper, :lower, nil The default value is `nil`. # [](Ash.Type.CiString.html#summary)Summary ## [Functions](Ash.Type.CiString.html#functions) [handle\_change?()](Ash.Type.CiString.html#handle_change?/0) [match(regex)](Ash.Type.CiString.html#match/1) [prepare\_change?()](Ash.Type.CiString.html#prepare_change?/0) # [](Ash.Type.CiString.html#functions)Functions [](Ash.Type.CiString.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/ci_string.ex#L1) [](Ash.Type.CiString.html#match/1) # match(regex) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/ci_string.ex#L242) [](Ash.Type.CiString.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/ci_string.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Comparable (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/comparable.ex#L1 "View Source") Helpers for working with [`Comparable`](Comparable.html) # [](Ash.Type.Comparable.html#summary)Summary ## [Functions](Ash.Type.Comparable.html#functions) [defcomparable(arg1, arg2, list)](Ash.Type.Comparable.html#defcomparable/3) # [](Ash.Type.Comparable.html#functions)Functions [](Ash.Type.Comparable.html#defcomparable/3) # defcomparable(arg1, arg2, list) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/comparable.ex#L3) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Date (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/date.ex#L1 "View Source") Represents a date in the database A builtin type that can be referenced via `:date` # [](Ash.Type.Date.html#summary)Summary ## [Functions](Ash.Type.Date.html#functions) [handle\_change?()](Ash.Type.Date.html#handle_change?/0) [prepare\_change?()](Ash.Type.Date.html#prepare_change?/0) # [](Ash.Type.Date.html#functions)Functions [](Ash.Type.Date.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/date.ex#L1) [](Ash.Type.Date.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/date.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.DateTime (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/datetime.ex#L1 "View Source") Represents a datetime, with configurable precision and timezone. # [](Ash.Type.DateTime.html#summary)Summary ## [Functions](Ash.Type.DateTime.html#functions) [handle\_change?()](Ash.Type.DateTime.html#handle_change?/0) [prepare\_change?()](Ash.Type.DateTime.html#prepare_change?/0) # [](Ash.Type.DateTime.html#functions)Functions [](Ash.Type.DateTime.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/datetime.ex#L1) [](Ash.Type.DateTime.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/datetime.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Decimal (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L1 "View Source") Represents a decimal. A builtin type that can be referenced via `:decimal` ### [](Ash.Type.Decimal.html#module-constraints)Constraints - `:max` - Enforces a maximum on the value - `:min` - Enforces a minimum on the value - `:greater_than` - Enforces a minimum on the value (exclusive) - `:less_than` - Enforces a maximum on the value (exclusive) # [](Ash.Type.Decimal.html#summary)Summary ## [Functions](Ash.Type.Decimal.html#functions) [handle\_change?()](Ash.Type.Decimal.html#handle_change?/0) [prepare\_change?()](Ash.Type.Decimal.html#prepare_change?/0) # [](Ash.Type.Decimal.html#functions)Functions [](Ash.Type.Decimal.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L1) [](Ash.Type.Decimal.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.DurationName (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/duration_name.ex#L1 "View Source") An interval of time, primarily meant to be used in expression functions Valid intervals are (as strings or atoms): \[:year, :month, :week, :day, :hour, :minute, :second, :millisecond, :microsecond] # [](Ash.Type.DurationName.html#summary)Summary ## [Types](Ash.Type.DurationName.html#types) [t()](Ash.Type.DurationName.html#t:t/0) ## [Functions](Ash.Type.DurationName.html#functions) [handle\_change?()](Ash.Type.DurationName.html#handle_change?/0) [prepare\_change?()](Ash.Type.DurationName.html#prepare_change?/0) # [](Ash.Type.DurationName.html#types)Types [](Ash.Type.DurationName.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/duration_name.ex#L8) ``` @type t() :: :microsecond | :millisecond | :second | :minute | :hour | :day | :week | :month | :year ``` # [](Ash.Type.DurationName.html#functions)Functions [](Ash.Type.DurationName.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/duration_name.ex#L1) [](Ash.Type.DurationName.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/duration_name.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Enum behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/enum.ex#L1 "View Source") A type for abstracting enums into a single type. For example, your existing attribute might look like: ``` attribute :status, :atom, constraints: [one_of: [:open, :closed]] ``` But as that starts to spread around your system, you may find that you want to centralize that logic. To do that, use this module to define an Ash type easily: ``` defmodule MyApp.TicketStatus do use Ash.Type.Enum, values: [:open, :closed] end ``` Then, you can rewrite your original attribute as follows: ``` attribute :status, MyApp.TicketStatus ``` Valid values are: - The atom itself, e.g `:open` - A string that matches the atom, e.g `"open"` - A string that matches the atom after being downcased, e.g `"OPEN"` or `"oPeN"` - A string that matches the stringified, downcased atom, after itself being downcased. This allows for enum values like `:Open`, `:SomeState` and `:Some_State` ## [](Ash.Type.Enum.html#module-custom-input-values)Custom input values If you need to accept inputs beyond those described above while still mapping them to one of the enum values, you can override the `match/1` callback. For example, if you want to map both the `:half_empty` and `:half_full` states to the same enum value, you could implement it as follows: ``` defmodule MyApp.GlassState do use Ash.Type.Enum, values: [:empty, :half_full, :full] def match(:half_empty), do: {:ok, :half_full} def match("half_empty"), do: {:ok, :half_full} def match(value), do: super(value) end ``` In the provided example, if no additional value is matched, `super(value)` is called, invoking the default implementation of `match/1`. This approach is typically suitable if you only aim to extend default matching rather than completely reimplementing it. ### [](Ash.Type.Enum.html#module-caveats)Caveats Additional input values are not exposed in derived interfaces. For example, `HALF_EMPTY` will not be present as a possible enum value when using `ash_graphql`. Moreover, only explicitly matched values are mapped to the enum value. For instance, `"HaLf_emPty"` would not be accepted by the code provided earlier. If case normalization is needed for additional values, it must be explicitly implemented. ## [](Ash.Type.Enum.html#module-value-descriptions)Value descriptions It's possible to associate a description with a value by passing a `{value, description}` tuple inside the values list, which becomes a keyword list: ``` defmodule MyApp.TicketStatus do use Ash.Type.Enum, values: [ open: "An open ticket", closed: "A closed ticket" ] end ``` This can be used by extensions to provide detailed descriptions of enum values. The description of a value can be retrieved with `description/1`: ``` MyApp.TicketStatus.description(:open) iex> "An open ticket" ``` # [](Ash.Type.Enum.html#summary)Summary ## [Callbacks](Ash.Type.Enum.html#callbacks) [description(arg1)](Ash.Type.Enum.html#c:description/1) The description of the value, if existing [match(term)](Ash.Type.Enum.html#c:match/1) finds the valid value that matches a given input term [match?(term)](Ash.Type.Enum.html#c:match?/1) true if a given term matches a value [values()](Ash.Type.Enum.html#c:values/0) The list of valid values (not all input types that match them) # [](Ash.Type.Enum.html#callbacks)Callbacks [](Ash.Type.Enum.html#c:description/1) # description(arg1) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/enum.ex#L91) ``` @callback description(atom() | String.t()) :: String.t() | nil ``` The description of the value, if existing [](Ash.Type.Enum.html#c:match/1) # match(term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/enum.ex#L95) ``` @callback match(term()) :: {:ok, atom()} | :error ``` finds the valid value that matches a given input term [](Ash.Type.Enum.html#c:match?/1) # match?(term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/enum.ex#L93) ``` @callback match?(term()) :: boolean() ``` true if a given term matches a value [](Ash.Type.Enum.html#c:values/0) # values() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/enum.ex#L89) ``` @callback values() :: [atom() | String.t()] ``` The list of valid values (not all input types that match them) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.File (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L1 "View Source") A type that represents a file on the filesystem. #### Persistence This type does not support persisting via [`Ash.DataLayer`](Ash.DataLayer.html). It is mainly intended to be used in [arguments](dsl-ash-resource.html#actions-action-argument). ## [](Ash.Type.File.html#module-valid-values-to-cast)Valid values to cast This type can cast multiple types of values: - itself - [`Plug.Upload`](../plug/1.16.1/Plug.Upload.html) - Any value that implements the [`Ash.Type.File.Source`](Ash.Type.File.Source.html) protocol. # [](Ash.Type.File.html#summary)Summary ## [Types](Ash.Type.File.html#types) [t()](Ash.Type.File.html#t:t/0) ## [Functions](Ash.Type.File.html#functions) [from\_io(device)](Ash.Type.File.html#from_io/1) Create a file from an `IO.device()` [from\_path(path)](Ash.Type.File.html#from_path/1) Create a file from a path. [handle\_change?()](Ash.Type.File.html#handle_change?/0) [open(file, modes \\\\ \[\])](Ash.Type.File.html#open/2) Open the file with the given `modes`. [path(file)](Ash.Type.File.html#path/1) Returns the path to the file. [prepare\_change?()](Ash.Type.File.html#prepare_change?/0) # [](Ash.Type.File.html#types)Types [](Ash.Type.File.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L30) ``` @type t() :: %Ash.Type.File{ implementation: Ash.Type.File.Implementation.t(), source: Ash.Type.File.Implementation.source() } ``` # [](Ash.Type.File.html#functions)Functions [](Ash.Type.File.html#from_io/1) # from\_io(device) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L122) ``` @spec from_io(device :: IO.device()) :: t() ``` Create a file from an `IO.device()` ## [](Ash.Type.File.html#from_io/1-example)Example ``` iex> path = "README.md" ...> {:ok, device} = File.open(path) ...> Ash.Type.File.from_io(device) %Ash.Type.File{source: device, implementation: Ash.Type.File.IO} ``` [](Ash.Type.File.html#from_path/1) # from\_path(path) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L108) ``` @spec from_path(path :: Path.t()) :: t() ``` Create a file from a path. ## [](Ash.Type.File.html#from_path/1-example)Example ``` iex> path = "README.md" ...> Ash.Type.File.from_path(path) %Ash.Type.File{source: "README.md", implementation: Ash.Type.File.Path} ``` [](Ash.Type.File.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L1) [](Ash.Type.File.html#open/2) # open(file, modes \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L94) ``` @spec open(file :: t(), modes :: [File.mode()]) :: {:ok, IO.device()} | {:error, Ash.Type.File.Implementation.error()} ``` Open the file with the given `modes`. This function will delegate to the [`open/2`](Ash.Type.File.html#open/2) function on the `implementation`. For details on the `modes` argument, see the [`File.open/2`](../elixir/File.html#open/2) documentation. ## [](Ash.Type.File.html#open/2-example)Example ``` iex> path = "README.md" ...> file = Ash.Type.File.from_path(path) ...> Ash.Type.File.open(file, [:read]) ...> # => {:ok, #PID<0.109.0>} ``` [](Ash.Type.File.html#path/1) # path(file) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L67) ``` @spec path(file :: t()) :: {:ok, Path.t()} | {:error, :not_supported | Ash.Type.File.Implementation.error()} ``` Returns the path to the file. Not every implementation will support this operation. If the implementation does not support this operation, then `{:error, :not_supported}` will be returned. In this case, use the [`open/2`](Ash.Type.File.html#open/2) function to access the file. ## [](Ash.Type.File.html#path/1-example)Example ``` iex> path = "README.md" ...> file = Ash.Type.File.from_path(path) ...> Ash.Type.File.path(file) {:ok, "README.md"} ``` [](Ash.Type.File.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.File.Implementation behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/implementation.ex#L1 "View Source") Behaviour for file implementations that are compatible with [`Ash.Type.File`](Ash.Type.File.html). # [](Ash.Type.File.Implementation.html#summary)Summary ## [Types](Ash.Type.File.Implementation.html#types) [error()](Ash.Type.File.Implementation.html#t:error/0) Errors returned by the implementation. [source()](Ash.Type.File.Implementation.html#t:source/0) The source of the file the implementation operates on. [t()](Ash.Type.File.Implementation.html#t:t/0) Any `module()` implementing the [`Ash.Type.File.Implementation`](Ash.Type.File.Implementation.html) behaviour. ## [Callbacks](Ash.Type.File.Implementation.html#callbacks) [open(file, modes)](Ash.Type.File.Implementation.html#c:open/2) Open `IO.device()` for the file. [path(file)](Ash.Type.File.Implementation.html#c:path/1) Return path of the file on disk. # [](Ash.Type.File.Implementation.html#types)Types [](Ash.Type.File.Implementation.html#t:error/0) # error() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/implementation.ex#L13) ``` @type error() :: term() ``` Errors returned by the implementation. [](Ash.Type.File.Implementation.html#t:source/0) # source() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/implementation.ex#L10) ``` @type source() :: term() ``` The source of the file the implementation operates on. [](Ash.Type.File.Implementation.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/implementation.ex#L7) ``` @type t() :: module() ``` Any `module()` implementing the [`Ash.Type.File.Implementation`](Ash.Type.File.Implementation.html) behaviour. # [](Ash.Type.File.Implementation.html#callbacks)Callbacks [](Ash.Type.File.Implementation.html#c:open/2) # open(file, modes) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/implementation.ex#L34) ``` @callback open(file :: source(), modes :: [File.mode()]) :: {:ok, IO.device()} | {:error, error()} ``` Open `IO.device()` for the file. See [`Ash.Type.File.open/2`](Ash.Type.File.html#open/2) The return pid must point to a process following the [Erlang I/O Protocol](https://www.erlang.org/doc/apps/stdlib/io_protocol.html) like [`StringIO`](../elixir/StringIO.html) or [`File`](../elixir/File.html). [](Ash.Type.File.Implementation.html#c:path/1) # path(file) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/implementation.ex#L23) ``` @callback path(file :: source()) :: {:ok, Path.t()} | {:error, error()} ``` Return path of the file on disk. See: [`Ash.Type.File.path/1`](Ash.Type.File.html#path/1) This callback is optional. If the file is not stored on disk, this callback can be omitted. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.File.Source protocol (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/source.ex#L1 "View Source") Protocol for allowing the casting of something into an [`Ash.Type.File`](Ash.Type.File.html). ## [](Ash.Type.File.Source.html#module-usage)Usage ``` defmodule MyStruct do defstruct [:path] @behavior Ash.Type.File.Implementation @impl Ash.Type.File.Implementation def path(%__MODULE__{path: path}), do: {:ok, path} @impl Ash.Type.File.Implementation def open(%__MODULE__{path: path}, modes), do: File.open(path, modes) defimpl Ash.Type.File.Source do def implementation(%MyStruct{} = struct), do: {:ok, MyStruct} end end ``` # [](Ash.Type.File.Source.html#summary)Summary ## [Types](Ash.Type.File.Source.html#types) [t()](Ash.Type.File.Source.html#t:t/0) All the types that implement this protocol. ## [Functions](Ash.Type.File.Source.html#functions) [implementation(file)](Ash.Type.File.Source.html#implementation/1) Detect Implementation of the file. # [](Ash.Type.File.Source.html#types)Types [](Ash.Type.File.Source.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/source.ex#L1) ``` @type t() :: term() ``` All the types that implement this protocol. # [](Ash.Type.File.Source.html#functions)Functions [](Ash.Type.File.Source.html#implementation/1) # implementation(file) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/file/source.ex#L37) ``` @spec implementation(t()) :: {:ok, Ash.Type.File.Implementation.t()} | :error ``` Detect Implementation of the file. Returns an `:ok` tuple with the implementation module if the file is supported and `:error` otherwise. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Float (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/float.ex#L1 "View Source") Represents a float (floating point number) A builtin type that be referenced via `:float` ### [](Ash.Type.Float.html#module-constraints)Constraints - `:max` - Enforces a maximum on the value - `:min` - Enforces a minimum on the value - `:greater_than` - Enforces a minimum on the value (exclusive) - `:less_than` - Enforces a maximum on the value (exclusive) # [](Ash.Type.Float.html#summary)Summary ## [Functions](Ash.Type.Float.html#functions) [handle\_change?()](Ash.Type.Float.html#handle_change?/0) [prepare\_change?()](Ash.Type.Float.html#prepare_change?/0) # [](Ash.Type.Float.html#functions)Functions [](Ash.Type.Float.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/float.ex#L1) [](Ash.Type.Float.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/float.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Function (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/function.ex#L1 "View Source") Represents a function. If the type would be dumped to a native format, `:erlang.term_to_binary(term, [:safe])` is used. Please keep in mind, this is *NOT SAFE* to use with external input. More information available here: [https://erlang.org/doc/man/erlang.html#binary\_to\_term-2](https://erlang.org/doc/man/erlang.html#binary_to_term-2) # [](Ash.Type.Function.html#summary)Summary ## [Functions](Ash.Type.Function.html#functions) [handle\_change?()](Ash.Type.Function.html#handle_change?/0) [prepare\_change?()](Ash.Type.Function.html#prepare_change?/0) # [](Ash.Type.Function.html#functions)Functions [](Ash.Type.Function.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/function.ex#L1) [](Ash.Type.Function.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/function.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1 "View Source") The [`Ash.Type`](Ash.Type.html) behaviour is used to define a value type in Ash. ## [](Ash.Type.html#module-built-in-types)Built in types - `:map` - [`Ash.Type.Map`](Ash.Type.Map.html) - `:keyword` - [`Ash.Type.Keyword`](Ash.Type.Keyword.html) - `:term` - [`Ash.Type.Term`](Ash.Type.Term.html) - `:atom` - [`Ash.Type.Atom`](Ash.Type.Atom.html) - `:string` - [`Ash.Type.String`](Ash.Type.String.html) - `:integer` - [`Ash.Type.Integer`](Ash.Type.Integer.html) - `:file` - [`Ash.Type.File`](Ash.Type.File.html) - `:float` - [`Ash.Type.Float`](Ash.Type.Float.html) - `:duration_name` - [`Ash.Type.DurationName`](Ash.Type.DurationName.html) - `:function` - [`Ash.Type.Function`](Ash.Type.Function.html) - `:boolean` - [`Ash.Type.Boolean`](Ash.Type.Boolean.html) - `:struct` - [`Ash.Type.Struct`](Ash.Type.Struct.html) - `:uuid` - [`Ash.Type.UUID`](Ash.Type.UUID.html) - `:uuid_v7` - [`Ash.Type.UUIDv7`](Ash.Type.UUIDv7.html) - `:binary` - [`Ash.Type.Binary`](Ash.Type.Binary.html) - `:date` - [`Ash.Type.Date`](Ash.Type.Date.html) - `:time` - [`Ash.Type.Time`](Ash.Type.Time.html) - `:decimal` - [`Ash.Type.Decimal`](Ash.Type.Decimal.html) - `:ci_string` - [`Ash.Type.CiString`](Ash.Type.CiString.html) - `:naive_datetime` - [`Ash.Type.NaiveDatetime`](Ash.Type.NaiveDatetime.html) - `:utc_datetime` - [`Ash.Type.UtcDatetime`](Ash.Type.UtcDatetime.html) - `:utc_datetime_usec` - [`Ash.Type.UtcDatetimeUsec`](Ash.Type.UtcDatetimeUsec.html) - `:datetime` - [`Ash.Type.DateTime`](Ash.Type.DateTime.html) - `:url_encoded_binary` - [`Ash.Type.UrlEncodedBinary`](Ash.Type.UrlEncodedBinary.html) - `:union` - [`Ash.Type.Union`](Ash.Type.Union.html) - `:module` - [`Ash.Type.Module`](Ash.Type.Module.html) - `:vector` - [`Ash.Type.Vector`](Ash.Type.Vector.html) ## [](Ash.Type.html#module-lists-arrays)Lists/Arrays To specify a list of values, use `{:array, Type}`. Arrays are special, and have special constraints: - `:items` ([`term/0`](../elixir/typespecs.html#built-in-types)) - Constraints for the elements of the list. See the contained type's docs for more. - `:min_length` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - A minimum length for the items. - `:max_length` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - A maximum length for the items. - `:nil_items?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not the list can contain nil items. The default value is `false`. - `:remove_nil_items?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Whether or not to remove the nil items from the list instead of adding errors. The default value is `false`. - `:empty_values` (list of [`term/0`](../elixir/typespecs.html#built-in-types)) - A set of values that, if encountered, will be considered an empty list. The default value is `[""]`. ## [](Ash.Type.html#module-defining-custom-types)Defining Custom Types Generally you add `use Ash.Type` to your module (it is possible to add `@behaviour Ash.Type` and define everything yourself, but this is more work and error-prone). Overriding the `{:array, type}` behaviour. By defining the `*_array` versions of `cast_input`, `cast_stored`, `dump_to_native` and `apply_constraints`, you can override how your type behaves as a collection. This is how the features of embedded resources are implemented. No need to implement them unless you wish to override the default behaviour. Your type is responsible for handling nil values in each callback as well. Simple example of a float custom type ``` defmodule GenTracker.AshFloat do use Ash.Type @impl Ash.Type def storage_type(_), do: :float @impl Ash.Type def cast_input(nil, _), do: {:ok, nil} def cast_input(value, _) do Ecto.Type.cast(:float, value) end @impl Ash.Type def cast_stored(nil, _), do: {:ok, nil} def cast_stored(value, _) do Ecto.Type.load(:float, value) end @impl Ash.Type def dump_to_native(nil, _), do: {:ok, nil} def dump_to_native(value, _) do Ecto.Type.dump(:float, value) end end ``` All the Ash built-in types are implemented with `use Ash.Type` so they are good examples to look at to create your own [`Ash.Type`](Ash.Type.html). ### [](Ash.Type.html#module-short-names)Short names You can define short `:atom_names` for your custom types by adding them to your Ash configuration: ``` config :ash, :custom_types, [ash_float: GenTracker.AshFloat] ``` Doing this will require a recompilation of the `:ash` dependency which can be triggered by calling: ``` $ mix deps.compile ash --force ``` ## [](Ash.Type.html#module-composite-types)Composite Types Composite types are composite *in the data layer*. Many data layers do not support this, but some (like AshPostgres), do. To define a composite type, the following things should be true: 1. A casted value should be a map or struct, for example for a point: `%{x: 1, y: 2}` 2. The data layer must support composite types, and the data layer representation will be a tuple, i.e `{1, 2}` 3. Define `def composite?(_), do: true` in your composite type 4. Define the type &amp; constraints of each item in the tuple, and its name in the map representation: `def composite_types(_), do: [{:x, :integer, []}, {:y, :integer, []}]`. You can also define a storage key for each item in the tuple, if the underlying type implementation has a different reference for an item, i.e `def composite_types(_), do: [{:x, :x_coord, :integer, []}, {:y, :y_coord, :integer, []}]` With the above implemented, your composite type can be used in expressions, for example: ``` Ash.Query.filter(expr(coordinates[:x] == 1)) ``` And you can also *construct* composite types in expressions, for example: ``` calculate :coordinates, :composite_point, expr( composite_type(%{x: some_value, y: some_other_value}, Point) ) ``` ## [](Ash.Type.html#module-constraints)Constraints Constraints are a way of validating an input type. This validation can be used in both attributes and arguments. The kinds of constraints you can apply depends on the type of data. You can find all types in [`Ash.Type`](Ash.Type.html) . Each type has its own page on which the available constraints are listed. For example in [`Ash.Type.String`](Ash.Type.String.html) you can find 5 constraints: - `:max_length` - `:min_length` - `:match` - `:trim?` - `:allow_empty?` You can also discover these constraints from iex: ``` $ iex -S mix iex(1)> Ash.Type.String.constraints [ max_length: [ type: :non_neg_integer, doc: "Enforces a maximum length on the value" ], min_length: [ type: :non_neg_integer, doc: "Enforces a minimum length on the value" ], match: [ type: {:custom, Ash.Type.String, :match, []}, doc: "Enforces that the string matches a passed in regex" ], trim?: [type: :boolean, doc: "Trims the value.", default: true], allow_empty?: [ type: :boolean, doc: "If false, the value is set to `nil` if it's empty.", default: false ] ] ``` ### [](Ash.Type.html#module-attribute-example)Attribute example To show how constraints can be used in a attribute, here is an example attribute describing a username: ``` defmodule MyProject.MyDomain.Account do # ... code_interface do define :create, action: :create end actions do default [:create, :read, :update, :destroy] end attributes do uuid_primary_key :id attribute :username, :string do constraints [ max_length: 20, min_length: 3, match: ~r/^[a-z_-]*$/, trim?: true, allow_empty?: false ] end end # ... end ``` If, when creating or updating this attribute, one of the constraints are not met, an error will be given telling you which constraint was broken. See below: ``` iex(1)> MyProject.MyDomain.Account.create!(%{username: "hi"}) ** (Ash.Error.Invalid) Invalid Error * Invalid value provided for username: length must be greater than or equal to 3. "hi" iex(2)> MyProject.MyDomain.Account.create!(%{username: "Hello there this is a long string"}) ** (Ash.Error.Invalid) Invalid Error * Invalid value provided for username: length must be less than or equal to 20. "Hello there this is a long string" iex(3)> MyProject.MyDomain.Account.create!(%{username: "hello there"}) ** (Ash.Error.Invalid) Invalid Error * Invalid value provided for username: must match the pattern ~r/^[a-z_-]*$/. "hello there" iex(4)> MyProject.MyDomain.Account.create!(%{username: ""}) ** (Ash.Error.Invalid) Invalid Error * attribute title is required ``` It will give you the resource as usual on successful requests: ``` iex(5)> MyProject.MyDomain.Account.create!(%{username: "hello"}) #MyProject.MyDomain.Account< __meta__: #Ecto.Schema.Metadata<:loaded, "account">, id: "7ba467dd-277c-4916-88ae-f62c93fee7a3", username: "hello", ... > ``` # [](Ash.Type.html#summary)Summary ## [Types](Ash.Type.html#types) [constraints()](Ash.Type.html#t:constraints/0) A keyword list of constraints for a type [error()](Ash.Type.html#t:error/0) An error value that can be returned from various callbacks [load\_context()](Ash.Type.html#t:load_context/0) The context that is provided to the [`load/4`](Ash.Type.html#c:load/4) callback. [merge\_load\_context()](Ash.Type.html#t:merge_load_context/0) The context that is provided to the [`merge_load/4`](Ash.Type.html#c:merge_load/4) callback. [t()](Ash.Type.html#t:t/0) A valid Ash.Type ## [Callbacks](Ash.Type.html#callbacks) [apply\_atomic\_constraints(new\_value, constraints)](Ash.Type.html#c:apply_atomic_constraints/2) Applies type constraints within an expression. [apply\_atomic\_constraints\_array(new\_value, constraints)](Ash.Type.html#c:apply_atomic_constraints_array/2) Applies type constraints to a list of values within an expression. See [`apply_atomic_constraints/2`](Ash.Type.html#c:apply_atomic_constraints/2) for more. [apply\_constraints(term, constraints)](Ash.Type.html#c:apply_constraints/2) Called after casting, to apply additional constraints to the value. [apply\_constraints\_array(list, constraints)](Ash.Type.html#c:apply_constraints_array/2) Called after casting a list of values, to apply additional constraints to the value. [array\_constraints()](Ash.Type.html#c:array_constraints/0) Returns a [`Spark.Options`](../spark/2.2.40/Spark.Options.html) spec for the additional constraints supported when used in a list. [can\_load?(constraints)](Ash.Type.html#c:can_load?/1) Whether or not [`load/4`](Ash.Type.html#c:load/4) can be used. Defined automatically [cast\_atomic(new\_value, constraints)](Ash.Type.html#c:cast_atomic/2) Casts a value within an expression. [cast\_atomic\_array(new\_value, constraints)](Ash.Type.html#c:cast_atomic_array/2) Casts a list of values within an expression. See [`cast_atomic/2`](Ash.Type.html#c:cast_atomic/2) for more. [cast\_in\_query?(constraints)](Ash.Type.html#c:cast_in_query?/1) Whether or not data layers that build queries should attempt to type cast values of this type while doing so. [cast\_input(term, constraints)](Ash.Type.html#c:cast_input/2) Attempt to cast unknown, potentially user-provided input, into a valid instance of the type. [cast\_input\_array(list, constraints)](Ash.Type.html#c:cast_input_array/2) Attempt to cast a list of unknown, potentially user-provided inputs, into a list of valid instances of type. [cast\_stored(term, constraints)](Ash.Type.html#c:cast_stored/2) Attempt to load a stored value from the data layer into a valid instance of the type. [cast\_stored\_array(list, constraints)](Ash.Type.html#c:cast_stored_array/2) Attempt to load a list of stored values from the data layer into a list of valid instances of the type. [composite?(constraints)](Ash.Type.html#c:composite?/1) Return true if the type is a composite type, meaning it is made up of one or more values. How this works is up to the data layer. [composite\_types(constraints)](Ash.Type.html#c:composite_types/1) Information about each member of the composite type, if it is a composite type [constraints()](Ash.Type.html#c:constraints/0) Returns a [`Spark.Options`](../spark/2.2.40/Spark.Options.html) spec for the constraints supported by the type. [custom\_apply\_constraints\_array?()](Ash.Type.html#c:custom_apply_constraints_array?/0) Whether or not an [`apply_constraints_array/2`](Ash.Type.html#c:apply_constraints_array/2) callback has been defined. This is defined automatically. [describe(constraints)](Ash.Type.html#c:describe/1) Describes a type given its constraints. Can be used to generate docs, for example. [dump\_to\_embedded(term, constraints)](Ash.Type.html#c:dump_to_embedded/2) Transform a valid instance of the type into a format that can be JSON encoded. [dump\_to\_embedded\_array(list, constraints)](Ash.Type.html#c:dump_to_embedded_array/2) Transform a list of valid instances of the type into a format that can be JSON encoded. [dump\_to\_native(term, constraints)](Ash.Type.html#c:dump_to_native/2) Transform a valid instance of the type into a format that the data layer can store. [dump\_to\_native\_array(list, constraints)](Ash.Type.html#c:dump_to_native_array/2) Transform a list of valid instance of the type into a format that the data layer can store. [ecto\_type()](Ash.Type.html#c:ecto_type/0) The underlying Ecto.Type. [embedded?()](Ash.Type.html#c:embedded?/0) Whether or not the type is an embedded resource. This is defined by embedded resources, you should not define this. [equal?(term, term)](Ash.Type.html#c:equal?/2) Determine if two valid instances of the type are equal. [evaluate\_operator(term)](Ash.Type.html#c:evaluate_operator/1) The implementation for any overloaded implementations. [generator(constraints)](Ash.Type.html#c:generator/1) An Enumerable that produces valid instances of the type. [get\_rewrites(merged\_load, calculation, path, constraints)](Ash.Type.html#c:get_rewrites/4) Gets any "rewrites" necessary to apply a given load statement. [handle\_change(old\_term, new\_term, constraints)](Ash.Type.html#c:handle_change/3) React to a changing value. This could be used, for example, to have a type like `:strictly_increasing_integer`. [handle\_change\_array(old\_term, new\_term, constraints)](Ash.Type.html#c:handle_change_array/3) React to a changing list of values. This could be used, for example, to have a type like `:unique_integer`, which when used in a list all items must be unique. [handle\_change\_array?()](Ash.Type.html#c:handle_change_array?/0) Whether or not a custom [`handle_change_array/3`](Ash.Type.html#c:handle_change_array/3) has been defined by the type. Defined automatically. [include\_source(constraints, t)](Ash.Type.html#c:include_source/2) Add the source changeset to the constraints, in cases where it is needed for type casting logic [init(constraints)](Ash.Type.html#c:init/1) Useful for typed data layers (like ash\_postgres) to instruct them not to attempt to cast input values. [load(values, load, constraints, context)](Ash.Type.html#c:load/4) Applies a load statement through a list of values. [loaded?(value, path\_to\_load, constraints, opts)](Ash.Type.html#c:loaded?/4) Checks if the given path has been loaded on the type. [matches\_type?(term, constraints)](Ash.Type.html#c:matches_type?/2) Whether or not the value a valid instance of the type. [merge\_load(left, right, constraints, context)](Ash.Type.html#c:merge_load/4) Merges a load statement with an existing load statement for the type. [operator\_overloads()](Ash.Type.html#c:operator_overloads/0) A map of operators with overloaded implementations. [prepare\_change(old\_term, new\_uncasted\_term, constraints)](Ash.Type.html#c:prepare_change/3) Prepare a change, given the old value and the new uncasted value. [prepare\_change\_array(old\_term, new\_uncasted\_term, constraints)](Ash.Type.html#c:prepare_change_array/3) Prepare a changing list of values, given the old value and the new uncasted value. [prepare\_change\_array?()](Ash.Type.html#c:prepare_change_array?/0) Whether or not a custom [`prepare_change_array/3`](Ash.Type.html#c:prepare_change_array/3) has been defined by the type. Defined automatically. [rewrite(value, list, constraints)](Ash.Type.html#c:rewrite/3) Apply any "rewrites" necessary to provide the results of a load statement to calculations that depended on a given load. [simple\_equality?()](Ash.Type.html#c:simple_equality?/0) Whether or not `==` can be used to compare instances of the type. [storage\_type()](Ash.Type.html#c:storage_type/0) The storage type, which should be known by a data layer supporting this type. [storage\_type(constraints)](Ash.Type.html#c:storage_type/1) The storage type, which should be known by a data layer supporting this type. ## [Functions](Ash.Type.html#functions) [apply\_atomic\_constraints(type, term, constraints)](Ash.Type.html#apply_atomic_constraints/3) Applies a types constraints to an expression. [apply\_constraints(type, term, constraints)](Ash.Type.html#apply_constraints/3) Confirms if a casted value matches the provided constraints. [array\_constraints(type)](Ash.Type.html#array_constraints/1) Gets the array constraints for a type [ash\_type?(module)](Ash.Type.html#ash_type?/1) Returns true if the value is a builtin type or adopts the [`Ash.Type`](Ash.Type.html) behaviour [builtin?(type)](Ash.Type.html#builtin?/1) Returns true if the type is an ash builtin type [can\_load?(type, constraints \\\\ \[\])](Ash.Type.html#can_load?/2) Returns true if the type supports nested loads [cast\_atomic(type, term, constraints)](Ash.Type.html#cast_atomic/3) Modifies an expression to apply a type's casting logic to the value it produces. [cast\_in\_query?(type, constraints \\\\ \[\])](Ash.Type.html#cast_in_query?/2) Returns `true` if the type should be cast in underlying queries [cast\_input(type, term, constraints \\\\ nil)](Ash.Type.html#cast_input/3) Casts input (e.g. unknown) data to an instance of the type, or errors [cast\_stored(type, term, constraints \\\\ \[\])](Ash.Type.html#cast_stored/3) Casts a value from the data store to an instance of the type, or errors [composite?(type, constraints)](Ash.Type.html#composite?/2) Returns true if the type is a composite type [composite\_types(type, constraints)](Ash.Type.html#composite_types/2) Returns the wrapped composite types [constraints(type)](Ash.Type.html#constraints/1) Returns the constraint schema for a type [describe(type, constraints)](Ash.Type.html#describe/2) Calls the type's `describe` function with the given constraints [determine\_types(types, values)](Ash.Type.html#determine_types/2) Determine types for a given function or operator. [dump\_to\_embedded(type, term, constraints \\\\ \[\])](Ash.Type.html#dump_to_embedded/3) Casts a value from the Elixir type to a value that can be embedded in another data structure. [dump\_to\_native(type, term, constraints \\\\ \[\])](Ash.Type.html#dump_to_native/3) Casts a value from the Elixir type to a value that the data store can persist [ecto\_type(type)](Ash.Type.html#ecto_type/1) Returns the ecto compatible type for an Ash.Type. [embedded\_type?(type)](Ash.Type.html#embedded_type?/1) Returns true if the type is an embedded resource [equal?(type, left, right)](Ash.Type.html#equal?/3) Determines if two values of a given type are equal. [generator(type, constraints)](Ash.Type.html#generator/2) Returns the StreamData generator for a given type [get\_rewrites(type, merged\_load, calculation, path, constraints)](Ash.Type.html#get_rewrites/5) Gets the load rewrites for a given type, load, calculation and path. [get\_type(value)](Ash.Type.html#get_type/1) Gets the type module for a given short name or module [get\_type!(value)](Ash.Type.html#get_type!/1) Gets the type module for a given short name or module, ensures that it is a valid `type` [handle\_change(type, old\_value, new\_value, constraints)](Ash.Type.html#handle_change/4) Process the old casted values alongside the new casted values. [handle\_change\_array?(type)](Ash.Type.html#handle_change_array?/1) Handles the change of a given array of values for an attribute change. Runs after casting. [include\_source(type, changeset\_or\_query, constraints)](Ash.Type.html#include_source/3) Provides the changeset, action\_input or query to the type, to potentially store in its constraints. [init(type, constraints)](Ash.Type.html#init/2) Initializes the constraints according to the underlying type [load(type, value, loads, constraints, context)](Ash.Type.html#load/5) Apply a load statement to a value. [loaded?(type, values, load, constraints, opts \\\\ \[\])](Ash.Type.html#loaded?/5) Checks if a given path has been loaded on a type. [matches\_type?(type, value, constraints \\\\ \[\])](Ash.Type.html#matches_type?/3) Detects as a best effort if an arbitrary value matches the given type [merge\_load(type, left, right, constraints, context)](Ash.Type.html#merge_load/5) Merges two load statements for a given type. [prepare\_change(type, old\_value, new\_value, constraints)](Ash.Type.html#prepare_change/4) Process the old casted values alongside the new *un*casted values. [prepare\_change\_array?(type)](Ash.Type.html#prepare_change_array?/1) Prepares a given array of values for an attribute change. Runs before casting. [rewrite(type, value, rewrites, constraints)](Ash.Type.html#rewrite/4) Applies rewrites to a given value. [short\_names()](Ash.Type.html#short_names/0) Returns the list of available type short names [simple\_equality?(type)](Ash.Type.html#simple_equality?/1) Determines if a type can be compared using the `==` operator. [storage\_type(type, constraints \\\\ \[\])](Ash.Type.html#storage_type/2) Returns the *underlying* storage type (the underlying type of the *ecto type* of the *ash type*) # [](Ash.Type.html#types)Types [](Ash.Type.html#t:constraints/0) # constraints() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L285) ``` @type constraints() :: Keyword.t() ``` A keyword list of constraints for a type [](Ash.Type.html#t:error/0) # error() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L289) ``` @type error() :: :error | {:error, String.t() | [field: atom(), fields: [atom()], message: String.t(), value: any()] | Ash.Error.t()} ``` An error value that can be returned from various callbacks [](Ash.Type.html#t:load_context/0) # load\_context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L302) ``` @type load_context() :: %{ domain: Ash.Domain.t(), actor: term() | nil, tenant: term(), tracer: [Ash.Tracer.t()] | Ash.Tracer.t() | nil, authorize?: boolean() | nil } ``` The context that is provided to the [`load/4`](Ash.Type.html#c:load/4) callback. [](Ash.Type.html#t:merge_load_context/0) # merge\_load\_context() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L316) ``` @type merge_load_context() :: %{ domain: Ash.Domain.t(), calc_name: term(), calc_load: term(), calc_path: [atom()], reuse_values?: boolean(), strict_loads?: boolean(), initial_data: term(), relationship_path: [atom()], authorize?: boolean() } ``` The context that is provided to the [`merge_load/4`](Ash.Type.html#c:merge_load/4) callback. [](Ash.Type.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L287) ``` @type t() :: module() | {:array, atom()} ``` A valid Ash.Type # [](Ash.Type.html#callbacks)Callbacks [](Ash.Type.html#c:apply_atomic_constraints/2) # apply\_atomic\_constraints(new\_value, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L502) ``` @callback apply_atomic_constraints(new_value :: Ash.Expr.t(), constraints()) :: :ok | {:ok, Ash.Expr.t()} | {:error, Ash.Error.t()} ``` Applies type constraints within an expression. [](Ash.Type.html#c:apply_atomic_constraints_array/2) # apply\_atomic\_constraints\_array(new\_value, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L506) ``` @callback apply_atomic_constraints_array(new_value :: Ash.Expr.t(), constraints()) :: :ok | {:ok, Ash.Expr.t()} | {:error, Ash.Error.t()} ``` Applies type constraints to a list of values within an expression. See [`apply_atomic_constraints/2`](Ash.Type.html#c:apply_atomic_constraints/2) for more. [](Ash.Type.html#c:apply_constraints/2) # apply\_constraints(term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L461) ``` @callback apply_constraints(term(), constraints()) :: {:ok, new_value :: term()} | :ok | error() ``` Called after casting, to apply additional constraints to the value. [](Ash.Type.html#c:apply_constraints_array/2) # apply\_constraints\_array(list, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L471) ``` @callback apply_constraints_array([term()], constraints()) :: {:ok, new_values :: [term()]} | :ok | error() ``` Called after casting a list of values, to apply additional constraints to the value. If not defined, [`apply_constraints/2`](Ash.Type.html#c:apply_constraints/2) is called for each item. [](Ash.Type.html#c:array_constraints/0) # array\_constraints() (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L458) ``` @callback array_constraints() :: constraints() ``` Returns a [`Spark.Options`](../spark/2.2.40/Spark.Options.html) spec for the additional constraints supported when used in a list. [](Ash.Type.html#c:can_load?/1) # can\_load?(constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L623) ``` @callback can_load?(constraints()) :: boolean() ``` Whether or not [`load/4`](Ash.Type.html#c:load/4) can be used. Defined automatically [](Ash.Type.html#c:cast_atomic/2) # cast\_atomic(new\_value, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L494) ``` @callback cast_atomic(new_value :: Ash.Expr.t(), constraints()) :: {:atomic, Ash.Expr.t()} | {:error, Ash.Error.t()} | {:not_atomic, String.t()} ``` Casts a value within an expression. For instance, if you had a type like `:non_neg_integer`, you might do: ``` def cast_atomic(value, _constraints) do expr( if ^value < 0 do error(Ash.Error.Changes.InvalidChanges, %{message: "must be positive", value: ^value}) else value end ) end ``` [](Ash.Type.html#c:cast_atomic_array/2) # cast\_atomic\_array(new\_value, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L498) ``` @callback cast_atomic_array(new_value :: Ash.Expr.t(), constraints()) :: {:atomic, Ash.Expr.t()} | {:error, Ash.Error.t()} | {:not_atomic, String.t()} ``` Casts a list of values within an expression. See [`cast_atomic/2`](Ash.Type.html#c:cast_atomic/2) for more. [](Ash.Type.html#c:cast_in_query?/1) # cast\_in\_query?(constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L365) ``` @callback cast_in_query?(constraints()) :: boolean() ``` Whether or not data layers that build queries should attempt to type cast values of this type while doing so. [](Ash.Type.html#c:cast_input/2) # cast\_input(term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L371) ``` @callback cast_input(term(), constraints()) :: {:ok, term()} | Ash.Error.t() ``` Attempt to cast unknown, potentially user-provided input, into a valid instance of the type. [](Ash.Type.html#c:cast_input_array/2) # cast\_input\_array(list, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L385) ``` @callback cast_input_array([term()], constraints()) :: {:ok, [term()]} | error() ``` Attempt to cast a list of unknown, potentially user-provided inputs, into a list of valid instances of type. This callback allows to define types that are "collection-aware", i.e an integer that is unique whenever it appears in a list. If not defined, [`cast_input/2`](Ash.Type.html#c:cast_input/2) is called for each item. [](Ash.Type.html#c:cast_stored/2) # cast\_stored(term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L388) ``` @callback cast_stored(term(), constraints()) :: {:ok, term()} | error() ``` Attempt to load a stored value from the data layer into a valid instance of the type. [](Ash.Type.html#c:cast_stored_array/2) # cast\_stored\_array(list, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L395) ``` @callback cast_stored_array([term()], constraints()) :: {:ok, [term()]} | error() ``` Attempt to load a list of stored values from the data layer into a list of valid instances of the type. If not defined, [`cast_stored/2`](Ash.Type.html#c:cast_stored/2) is called for each item. [](Ash.Type.html#c:composite?/1) # composite?(constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L514) ``` @callback composite?(constraints()) :: boolean() ``` Return true if the type is a composite type, meaning it is made up of one or more values. How this works is up to the data layer. For example, `AshMoney` provides a type that is composite with a "currency" and an "amount". [](Ash.Type.html#c:composite_types/1) # composite\_types(constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L523) ``` @callback composite_types(constraints()) :: [ {name, type, constraints()} | {name, storage_key, type, constraints()} ] when name: atom(), type: t(), storage_key: atom() ``` Information about each member of the composite type, if it is a composite type An example given the `AshMoney` example listed above: `[{:currency, :string, []}, {:amount, :decimal, []}]` [](Ash.Type.html#c:constraints/0) # constraints() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L455) ``` @callback constraints() :: constraints() ``` Returns a [`Spark.Options`](../spark/2.2.40/Spark.Options.html) spec for the constraints supported by the type. [](Ash.Type.html#c:custom_apply_constraints_array?/0) # custom\_apply\_constraints\_array?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L561) ``` @callback custom_apply_constraints_array?() :: boolean() ``` Whether or not an [`apply_constraints_array/2`](Ash.Type.html#c:apply_constraints_array/2) callback has been defined. This is defined automatically. [](Ash.Type.html#c:describe/1) # describe(constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L528) ``` @callback describe(constraints()) :: String.t() | nil ``` Describes a type given its constraints. Can be used to generate docs, for example. [](Ash.Type.html#c:dump_to_embedded/2) # dump\_to\_embedded(term, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L409) ``` @callback dump_to_embedded(term(), constraints()) :: {:ok, term()} | :error ``` Transform a valid instance of the type into a format that can be JSON encoded. [](Ash.Type.html#c:dump_to_embedded_array/2) # dump\_to\_embedded\_array(list, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L416) ``` @callback dump_to_embedded_array([term()], constraints()) :: {:ok, term()} | error() ``` Transform a list of valid instances of the type into a format that can be JSON encoded. If not defined, [`dump_to_embedded/2`](Ash.Type.html#c:dump_to_embedded/2) is called for each item. [](Ash.Type.html#c:dump_to_native/2) # dump\_to\_native(term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L399) ``` @callback dump_to_native(term(), constraints()) :: {:ok, term()} | error() ``` Transform a valid instance of the type into a format that the data layer can store. [](Ash.Type.html#c:dump_to_native_array/2) # dump\_to\_native\_array(list, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L406) ``` @callback dump_to_native_array([term()], constraints()) :: {:ok, term()} | error() ``` Transform a list of valid instance of the type into a format that the data layer can store. If not defined, [`dump_to_native/2`](Ash.Type.html#c:dump_to_native/2) is called for each item. [](Ash.Type.html#c:ecto_type/0) # ecto\_type() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L368) ``` @callback ecto_type() :: Ecto.Type.t() ``` The underlying Ecto.Type. [](Ash.Type.html#c:embedded?/0) # embedded?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L550) ``` @callback embedded?() :: boolean() ``` Whether or not the type is an embedded resource. This is defined by embedded resources, you should not define this. [](Ash.Type.html#c:equal?/2) # equal?(term, term) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L535) ``` @callback equal?(term(), term()) :: boolean() ``` Determine if two valid instances of the type are equal. *Do not define this* if `==` is sufficient for your type. See [`simple_equality?/0`](Ash.Type.html#c:simple_equality?/0) for more. [](Ash.Type.html#c:evaluate_operator/1) # evaluate\_operator(term) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L355) ``` @callback evaluate_operator(term()) :: {:known, term()} | :unknown | {:error, term()} ``` The implementation for any overloaded implementations. [](Ash.Type.html#c:generator/1) # generator(constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L558) ``` @callback generator(constraints()) :: Enumerable.t() ``` An Enumerable that produces valid instances of the type. This can be used for property testing, or generating valid inputs for seeding. Typically you would use [`StreamData`](../stream_data/1.1.2/StreamData.html) for this. [](Ash.Type.html#c:get_rewrites/4) # get\_rewrites(merged\_load, calculation, path, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L606) ``` @callback get_rewrites( merged_load :: term(), calculation :: Ash.Query.Calculation.t(), path :: [atom()], constraints :: Keyword.t() ) :: [rewrite()] ``` Gets any "rewrites" necessary to apply a given load statement. This is a low level tool used when types can contain instances of resources. You generally should not need to know how this works. See [`Ash.Type.Union`](Ash.Type.Union.html) and [`Ash.Type.Struct`](Ash.Type.Struct.html) for examples if you are trying to write a similar type. [](Ash.Type.html#c:handle_change/3) # handle\_change(old\_term, new\_term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L419) ``` @callback handle_change(old_term :: term(), new_term :: term(), constraints()) :: {:ok, term()} | error() ``` React to a changing value. This could be used, for example, to have a type like `:strictly_increasing_integer`. [](Ash.Type.html#c:handle_change_array/3) # handle\_change\_array(old\_term, new\_term, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L427) ``` @callback handle_change_array(old_term :: [term()], new_term :: [term()], constraints()) :: {:ok, term()} | error() ``` React to a changing list of values. This could be used, for example, to have a type like `:unique_integer`, which when used in a list all items must be unique. If not defined, [`handle_change/3`](Ash.Type.html#c:handle_change/3) is called for each item with a `nil` old value. [](Ash.Type.html#c:handle_change_array?/0) # handle\_change\_array?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L452) ``` @callback handle_change_array?() :: boolean() ``` Whether or not a custom [`handle_change_array/3`](Ash.Type.html#c:handle_change_array/3) has been defined by the type. Defined automatically. [](Ash.Type.html#c:include_source/2) # include\_source(constraints, t) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L341) ``` @callback include_source(constraints(), Ash.Changeset.t()) :: constraints() ``` Add the source changeset to the constraints, in cases where it is needed for type casting logic [](Ash.Type.html#c:init/1) # init(constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L362) ``` @callback init(constraints()) :: {:ok, constraints()} | {:error, Ash.Error.t()} ``` Useful for typed data layers (like ash\_postgres) to instruct them not to attempt to cast input values. You generally won't need this, but it can be an escape hatch for certain cases. [](Ash.Type.html#c:load/4) # load(values, load, constraints, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L569) ``` @callback load( values :: [term()], load :: Keyword.t(), constraints :: Keyword.t(), context :: load_context() ) :: {:ok, [term()]} | {:error, Ash.Error.t()} ``` Applies a load statement through a list of values. This allows types to support load statements, like [`Ash.Type.Union`](Ash.Type.Union.html), embedded resources, or the [`Ash.Type.Struct`](Ash.Type.Struct.html) when it is an `instance_of` a resource. [](Ash.Type.html#c:loaded?/4) # loaded?(value, path\_to\_load, constraints, opts) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L580) ``` @callback loaded?( value :: term(), path_to_load :: [atom()], constraints :: Keyword.t(), opts :: Keyword.t() ) :: boolean() ``` Checks if the given path has been loaded on the type. [](Ash.Type.html#c:matches_type?/2) # matches\_type?(term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L375) ``` @callback matches_type?(term(), constraints()) :: boolean() ``` Whether or not the value a valid instance of the type. [](Ash.Type.html#c:merge_load/4) # merge\_load(left, right, constraints, context) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L590) ``` @callback merge_load( left :: term(), right :: term(), constraints :: Keyword.t(), context :: merge_load_context() | nil ) :: {:ok, term()} | {:error, error()} | :error ``` Merges a load statement with an existing load statement for the type. [](Ash.Type.html#c:operator_overloads/0) # operator\_overloads() (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L350) ``` @callback operator_overloads() :: %{optional(atom()) => %{optional(term()) => module()}} ``` A map of operators with overloaded implementations. These will only be honored if the type is placed in `config :ash, :known_types, [...Type]` A corresponding `evaluate_operator/1` clause should match. [](Ash.Type.html#c:prepare_change/3) # prepare\_change(old\_term, new\_uncasted\_term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L433) ``` @callback prepare_change(old_term :: term(), new_uncasted_term :: term(), constraints()) :: {:ok, term()} | error() ``` Prepare a change, given the old value and the new uncasted value. [](Ash.Type.html#c:prepare_change_array/3) # prepare\_change\_array(old\_term, new\_uncasted\_term, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L441) ``` @callback prepare_change_array( old_term :: [term()], new_uncasted_term :: [term()], constraints() ) :: {:ok, term()} | error() ``` Prepare a changing list of values, given the old value and the new uncasted value. If not defined, [`prepare_change/3`](Ash.Type.html#c:prepare_change/3) is called for each item with a `nil` old value. [](Ash.Type.html#c:prepare_change_array?/0) # prepare\_change\_array?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L449) ``` @callback prepare_change_array?() :: boolean() ``` Whether or not a custom [`prepare_change_array/3`](Ash.Type.html#c:prepare_change_array/3) has been defined by the type. Defined automatically. [](Ash.Type.html#c:rewrite/3) # rewrite(value, list, constraints) (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L620) ``` @callback rewrite(value :: term(), [rewrite()], constraints :: Keyword.t()) :: value :: term() ``` Apply any "rewrites" necessary to provide the results of a load statement to calculations that depended on a given load. This is a low level tool used when types can contain instances of resources. You generally should not need to know how this works. See [`Ash.Type.Union`](Ash.Type.Union.html) and [`Ash.Type.Struct`](Ash.Type.Struct.html) for examples if you are trying to write a similar type. [](Ash.Type.html#c:simple_equality?/0) # simple\_equality?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L547) ``` @callback simple_equality?() :: boolean() ``` Whether or not `==` can be used to compare instances of the type. This is defined automatically to return `false` if [`equal?/2`](Ash.Type.html#c:equal?/2) is defined. Types that cannot be compared using `==` incur significant runtime costs when used in certain ways. For example, if a resource's primary key cannot be compared with `==`, we cannot do things like key a list of records by their primary key. Implementing [`equal?/2`](Ash.Type.html#c:equal?/2) will cause various code paths to be considerably slower, so only do it when necessary. [](Ash.Type.html#c:storage_type/0) # storage\_type() (optional)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L333) ``` @callback storage_type() :: Ecto.Type.t() ``` The storage type, which should be known by a data layer supporting this type. Use [`storage_type/1`](Ash.Type.html#c:storage_type/1), as this will be deprecated in the future. [](Ash.Type.html#c:storage_type/1) # storage\_type(constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L338) ``` @callback storage_type(constraints()) :: Ecto.Type.t() ``` The storage type, which should be known by a data layer supporting this type. # [](Ash.Type.html#functions)Functions [](Ash.Type.html#apply_atomic_constraints/3) # apply\_atomic\_constraints(type, term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1295) ``` @spec apply_atomic_constraints(t(), term(), constraints()) :: {:ok, Ash.Expr.t()} | {:error, Ash.Error.t()} ``` Applies a types constraints to an expression. This delegates to the underlying types implementaiton of [`apply_atomic_constraints/2`](Ash.Type.html#c:apply_atomic_constraints/2). [](Ash.Type.html#apply_constraints/3) # apply\_constraints(type, term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1070) ``` @spec apply_constraints(t(), term(), constraints()) :: {:ok, term()} | {:error, String.t()} ``` Confirms if a casted value matches the provided constraints. [](Ash.Type.html#array_constraints/1) # array\_constraints(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L683) Gets the array constraints for a type [](Ash.Type.html#ash_type?/1) # ash\_type?(module) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L906) ``` @spec ash_type?(term()) :: boolean() ``` Returns true if the value is a builtin type or adopts the [`Ash.Type`](Ash.Type.html) behaviour [](Ash.Type.html#builtin?/1) # builtin?(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L658) Returns true if the type is an ash builtin type [](Ash.Type.html#can_load?/2) # can\_load?(type, constraints \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1562) ``` @spec can_load?(t(), Keyword.t()) :: boolean() ``` Returns true if the type supports nested loads [](Ash.Type.html#cast_atomic/3) # cast\_atomic(type, term, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1248) ``` @spec cast_atomic(t(), term(), constraints()) :: {:atomic, Ash.Expr.t()} | {:ok, term()} | {:error, Ash.Error.t()} | {:not_atomic, String.t()} ``` Modifies an expression to apply a type's casting logic to the value it produces. This delegates to the underlying types implementaiton of [`cast_atomic/2`](Ash.Type.html#c:cast_atomic/2). [](Ash.Type.html#cast_in_query?/2) # cast\_in\_query?(type, constraints \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1203) Returns `true` if the type should be cast in underlying queries [](Ash.Type.html#cast_input/3) # cast\_input(type, term, constraints \\\\ nil) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L920) ``` @spec cast_input(t(), term(), constraints() | nil) :: {:ok, term()} | {:error, Keyword.t()} | :error ``` Casts input (e.g. unknown) data to an instance of the type, or errors Maps to [`Ecto.Type.cast/2`](../ecto/3.12.5/Ecto.Type.html#cast/2) [](Ash.Type.html#cast_stored/3) # cast\_stored(type, term, constraints \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1045) ``` @spec cast_stored(t(), term(), constraints() | nil) :: {:ok, term()} | {:error, keyword()} | :error ``` Casts a value from the data store to an instance of the type, or errors Maps to [`Ecto.Type.load/2`](../ecto/3.12.5/Ecto.Type.html#load/2) [](Ash.Type.html#composite?/2) # composite?(type, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L743) ``` @spec composite?( t(), constraints() ) :: Enumerable.t() ``` Returns true if the type is a composite type [](Ash.Type.html#composite_types/2) # composite\_types(type, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L753) ``` @spec composite_types( t(), constraints() ) :: Enumerable.t() ``` Returns the wrapped composite types [](Ash.Type.html#constraints/1) # constraints(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1193) ``` @spec constraints(t()) :: constraints() ``` Returns the constraint schema for a type [](Ash.Type.html#describe/2) # describe(type, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L672) Calls the type's `describe` function with the given constraints [](Ash.Type.html#determine_types/2) # determine\_types(types, values) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1956) Determine types for a given function or operator. [](Ash.Type.html#dump_to_embedded/3) # dump\_to\_embedded(type, term, constraints \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1326) ``` @spec dump_to_embedded(t(), term(), constraints() | nil) :: {:ok, term()} | {:error, keyword()} | :error ``` Casts a value from the Elixir type to a value that can be embedded in another data structure. Embedded resources expect to be stored in JSON, so this allows things like UUIDs to be stored as strings in embedded resources instead of binary. [](Ash.Type.html#dump_to_native/3) # dump\_to\_native(type, term, constraints \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1222) ``` @spec dump_to_native(t(), term(), constraints() | nil) :: {:ok, term()} | {:error, keyword()} | :error ``` Casts a value from the Elixir type to a value that the data store can persist Maps to [`Ecto.Type.dump/2`](../ecto/3.12.5/Ecto.Type.html#dump/2) [](Ash.Type.html#ecto_type/1) # ecto\_type(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L890) ``` @spec ecto_type(t()) :: Ecto.Type.t() ``` Returns the ecto compatible type for an Ash.Type. If you `use Ash.Type`, this is created for you. For builtin types this may return a corresponding ecto builtin type (atom) [](Ash.Type.html#embedded_type?/1) # embedded\_type?(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L662) Returns true if the type is an embedded resource [](Ash.Type.html#equal?/3) # equal?(type, left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1350) ``` @spec equal?(t(), term(), term()) :: boolean() ``` Determines if two values of a given type are equal. Maps to [`Ecto.Type.equal?/3`](../ecto/3.12.5/Ecto.Type.html#equal?/3) [](Ash.Type.html#generator/2) # generator(type, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L772) ``` @spec generator( module() | {:array, module()}, constraints() ) :: Enumerable.t() ``` Returns the StreamData generator for a given type [](Ash.Type.html#get_rewrites/5) # get\_rewrites(type, merged\_load, calculation, path, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1494) Gets the load rewrites for a given type, load, calculation and path. This is used for defining types that support a nested load statement. See the embedded type and union type implementations for examples of how to use this. [](Ash.Type.html#get_type/1) # get\_type(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L694) ``` @spec get_type(atom() | module() | {:array, atom() | module()}) :: atom() | module() | {:array, atom() | module()} ``` Gets the type module for a given short name or module [](Ash.Type.html#get_type!/1) # get\_type!(value) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L719) ``` @spec get_type!(atom() | module() | {:array, atom() | module()}) :: atom() | module() | {:array, atom() | module()} ``` Gets the type module for a given short name or module, ensures that it is a valid `type` ## [](Ash.Type.html#get_type!/1-raises)Raises - [`RuntimeError`](../elixir/RuntimeError.html): If the provided type module is not found or invalid. [](Ash.Type.html#handle_change/4) # handle\_change(type, old\_value, new\_value, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L819) Process the old casted values alongside the new casted values. This is leveraged by embedded types to know if something is being updated or destroyed. This is not called on creates. [](Ash.Type.html#handle_change_array?/1) # handle\_change\_array?(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1582) ``` @spec handle_change_array?(t()) :: boolean() ``` Handles the change of a given array of values for an attribute change. Runs after casting. [](Ash.Type.html#include_source/3) # include\_source(type, changeset\_or\_query, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1372) ``` @spec include_source( t(), Ash.Changeset.t() | Ash.Query.t() | Ash.ActionInput.t(), constraints() ) :: constraints() ``` Provides the changeset, action\_input or query to the type, to potentially store in its constraints. This is used for embedded types to allow accessing the parent changeset in certain cases. [](Ash.Type.html#init/2) # init(type, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L858) ``` @spec init(t(), constraints()) :: {:ok, constraints()} | {:error, Ash.Error.t()} ``` Initializes the constraints according to the underlying type [](Ash.Type.html#load/5) # load(type, value, loads, constraints, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1461) ``` @spec load( type :: t(), values :: [term()], load :: Keyword.t(), constraints :: Keyword.t(), context :: load_context() ) :: {:ok, [term()]} | {:error, Ash.Error.t()} ``` Apply a load statement to a value. This is used for types that can be "loaded through". For example, maps, unions and structs. If they have keys that are embedded types, for example, we want to be able to apply a load statements to their contents. [](Ash.Type.html#loaded?/5) # loaded?(type, values, load, constraints, opts \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1425) ``` @spec loaded?( type :: t(), value_or_values :: term(), path_to_load :: [atom()], constraints :: Keyword.t(), opts :: Keyword.t() ) :: boolean() ``` Checks if a given path has been loaded on a type. This is used to "load through" types. For more see [`load/5`](Ash.Type.html#load/5). [](Ash.Type.html#matches_type?/3) # matches\_type?(type, value, constraints \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1020) Detects as a best effort if an arbitrary value matches the given type [](Ash.Type.html#merge_load/5) # merge\_load(type, left, right, constraints, context) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1398) ``` @spec merge_load( type :: t(), left :: term(), right :: term(), constraints :: Keyword.t(), context :: merge_load_context() | nil ) :: {:ok, [term()]} | :error | {:error, Ash.Error.t()} ``` Merges two load statements for a given type. This is used to "load through" types. For more see [`load/5`](Ash.Type.html#load/5). [](Ash.Type.html#prepare_change/4) # prepare\_change(type, old\_value, new\_value, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L840) Process the old casted values alongside the new *un*casted values. This is leveraged by embedded types to know if something is being updated or destroyed. This is not called on creates. [](Ash.Type.html#prepare_change_array?/1) # prepare\_change\_array?(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1572) ``` @spec prepare_change_array?(t()) :: boolean() ``` Prepares a given array of values for an attribute change. Runs before casting. [](Ash.Type.html#rewrite/4) # rewrite(type, value, rewrites, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1510) Applies rewrites to a given value. This is used for defining types that support a nested load statement. See the embedded type and union type implementations for examples of how to use this. [](Ash.Type.html#short_names/0) # short\_names() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L655) Returns the list of available type short names [](Ash.Type.html#simple_equality?/1) # simple\_equality?(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L1594) ``` @spec simple_equality?(t()) :: boolean() ``` Determines if a type can be compared using the `==` operator. [](Ash.Type.html#storage_type/2) # storage\_type(type, constraints \\\\ \[]) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/type.ex#L879) Returns the *underlying* storage type (the underlying type of the *ecto type* of the *ash type*) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Integer (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/integer.ex#L1 "View Source") Represents a simple integer A builtin type that can be referenced via `:integer` ### [](Ash.Type.Integer.html#module-constraints)Constraints - `:max` - Enforces a maximum on the value - `:min` - Enforces a minimum on the value # [](Ash.Type.Integer.html#summary)Summary ## [Functions](Ash.Type.Integer.html#functions) [handle\_change?()](Ash.Type.Integer.html#handle_change?/0) [prepare\_change?()](Ash.Type.Integer.html#prepare_change?/0) # [](Ash.Type.Integer.html#functions)Functions [](Ash.Type.Integer.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/integer.ex#L1) [](Ash.Type.Integer.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/integer.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Keyword (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/keyword.ex#L1 "View Source") Represents a keyword list, stored as a `:map` in the database. A builtin type that can be referenced via `:keyword_list` - `:fields` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - Required. The types of the fields in the keyword, and their constraints. If constraints are specified, only those fields will be in the casted keyword. For example: ``` fields: [ amount: [ type: :integer, constraints: [ max: 10 ] ], currency: [ type: :string, allow_nil?: false, constraints: [ max_length: 3 ] ] ] ``` allow\_nil? is true by default - `:type` (an [`Ash.Type`](Ash.Type.html)) - Required. - `:allow_nil?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - The default value is `true`. - `:constraints` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - The default value is `[]`. # [](Ash.Type.Keyword.html#summary)Summary ## [Functions](Ash.Type.Keyword.html#functions) [handle\_change?()](Ash.Type.Keyword.html#handle_change?/0) [prepare\_change?()](Ash.Type.Keyword.html#prepare_change?/0) # [](Ash.Type.Keyword.html#functions)Functions [](Ash.Type.Keyword.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/keyword.ex#L1) [](Ash.Type.Keyword.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/keyword.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Map (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/map.ex#L1 "View Source") Represents a map stored in the database. In postgres, for example, this represents binary encoded json A builtin type that can be referenced via `:map` - `:fields` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - The types of the fields in the map, and their constraints. If constraints are specified, only those fields will be in the casted map. For example: ``` fields: [ amount: [ type: :integer, constraints: [ max: 10 ] ], currency: [ type: :string, allow_nil?: false, constraints: [ max_length: 3 ] ] ] ``` allow\_nil? is true by default - `:type` (an [`Ash.Type`](Ash.Type.html)) - Required. - `:allow_nil?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - The default value is `true`. - `:constraints` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - The default value is `[]`. # [](Ash.Type.Map.html#summary)Summary ## [Functions](Ash.Type.Map.html#functions) [handle\_change?()](Ash.Type.Map.html#handle_change?/0) [prepare\_change?()](Ash.Type.Map.html#prepare_change?/0) # [](Ash.Type.Map.html#functions)Functions [](Ash.Type.Map.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/map.ex#L1) [](Ash.Type.Map.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/map.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Module (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/module.ex#L1 "View Source") Stores a module as a string in the database. A builtin type that can be referenced via `:module`. ### [](Ash.Type.Module.html#module-constraints)Constraints - `:behaviour` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Allows constraining the module a one which implements a behaviour - `:protocol` ([`atom/0`](../elixir/typespecs.html#basic-types)) - Allows constraining the module a one which implements a protocol # [](Ash.Type.Module.html#summary)Summary ## [Functions](Ash.Type.Module.html#functions) [handle\_change?()](Ash.Type.Module.html#handle_change?/0) [prepare\_change?()](Ash.Type.Module.html#prepare_change?/0) # [](Ash.Type.Module.html#functions)Functions [](Ash.Type.Module.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/module.ex#L1) [](Ash.Type.Module.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/module.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.NaiveDatetime (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/naive_datetime.ex#L1 "View Source") Represents a Naive datetime A builtin type that can be referenced via `:naive_datetime` # [](Ash.Type.NaiveDatetime.html#summary)Summary ## [Functions](Ash.Type.NaiveDatetime.html#functions) [handle\_change?()](Ash.Type.NaiveDatetime.html#handle_change?/0) [prepare\_change?()](Ash.Type.NaiveDatetime.html#prepare_change?/0) # [](Ash.Type.NaiveDatetime.html#functions)Functions [](Ash.Type.NaiveDatetime.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/naive_datetime.ex#L1) [](Ash.Type.NaiveDatetime.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/naive_datetime.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.NewType behaviour (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L1 "View Source") Allows defining a new type that is the combination of an existing type and custom constraints A subtle difference between this type and its supertype (one that will almost certainly not matter in any case) is that we use the `apply_constraints` logic of the underlying type in the same step as `cast_input`. We do this because new types like these are, generally speaking, considering the constraint application as part of the core type. Other types, if you simply do [`Ash.Type.cast_input/3`](Ash.Type.html#cast_input/3) you will not be also applying their constraints. ## [](Ash.Type.NewType.html#module-options)Options - `:subtype_of` - The type that this new type is a subtype of. - `:constraints` - The constraints that this new type uses for the underlying type. - `:lazy_init?` - If true, the `init/1` function will be called at runtime instead of compile time. Allows for recursive types. For Example: ``` defmodule MyApp.Types.SSN do use Ash.Type.NewType, subtype_of: :string, constraints: [match: ~r/regex for ssn/] end defmodule MyApp.Types.Metadata do use Ash.Type.NewType, subtype_of: :union, constraints: [types: [ foo: [...], bar: [...] ]] end ``` # [](Ash.Type.NewType.html#summary)Summary ## [Types](Ash.Type.NewType.html#types) [t()](Ash.Type.NewType.html#t:t/0) ## [Callbacks](Ash.Type.NewType.html#callbacks) [subtype\_constraints()](Ash.Type.NewType.html#c:subtype_constraints/0) Returns the underlying subtype constraints [subtype\_of()](Ash.Type.NewType.html#c:subtype_of/0) Returns the type that the NewType is a subtype of. [type\_constraints(constraints, subtype\_constraints)](Ash.Type.NewType.html#c:type_constraints/2) Returns the modified NewType constraints ## [Functions](Ash.Type.NewType.html#functions) [constraints(type, constraints)](Ash.Type.NewType.html#constraints/2) Returns the constraints schema. [new\_type?(type)](Ash.Type.NewType.html#new_type?/1) Returns true if the corresponding type is an Ash.Type.NewType [subtype\_of(type)](Ash.Type.NewType.html#subtype_of/1) Returns the type that the given newtype is a subtype of # [](Ash.Type.NewType.html#types)Types [](Ash.Type.NewType.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L42) ``` @type t() :: module() | atom() | {:array, module() | atom()} ``` # [](Ash.Type.NewType.html#callbacks)Callbacks [](Ash.Type.NewType.html#c:subtype_constraints/0) # subtype\_constraints() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L37) ``` @callback subtype_constraints() :: Keyword.t() ``` Returns the underlying subtype constraints [](Ash.Type.NewType.html#c:subtype_of/0) # subtype\_of() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L35) ``` @callback subtype_of() :: module() | atom() ``` Returns the type that the NewType is a subtype of. [](Ash.Type.NewType.html#c:type_constraints/2) # type\_constraints(constraints, subtype\_constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L39) ``` @callback type_constraints(constraints :: Keyword.t(), subtype_constraints :: Keyword.t()) :: Keyword.t() ``` Returns the modified NewType constraints # [](Ash.Type.NewType.html#functions)Functions [](Ash.Type.NewType.html#constraints/2) # constraints(type, constraints) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L69) ``` @spec constraints(Ash.Type.t(), Keyword.t()) :: Keyword.t() ``` Returns the constraints schema. [](Ash.Type.NewType.html#new_type?/1) # new\_type?(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L46) ``` @spec new_type?(Ash.Type.t()) :: boolean() ``` Returns true if the corresponding type is an Ash.Type.NewType [](Ash.Type.NewType.html#subtype_of/1) # subtype\_of(type) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/new_type.ex#L51) ``` @spec subtype_of(t()) :: Ash.Type.t() ``` Returns the type that the given newtype is a subtype of [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.String (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/string.ex#L1 "View Source") Stores a string in the database. A built-in type that can be referenced via `:string`. By default, values are trimmed and empty values are set to `nil`. You can use the `allow_empty?` and `trim?` constraints to change these behaviors. ### [](Ash.Type.String.html#module-constraints)Constraints - `:max_length` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Enforces a maximum length on the value - `:min_length` ([`non_neg_integer/0`](../elixir/typespecs.html#basic-types)) - Enforces a minimum length on the value - `:match` - Enforces that the string matches a passed in regex - `:trim?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - Trims the value. The default value is `true`. - `:allow_empty?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If false, the value is set to `nil` if it's empty. The default value is `false`. # [](Ash.Type.String.html#summary)Summary ## [Functions](Ash.Type.String.html#functions) [handle\_change?()](Ash.Type.String.html#handle_change?/0) [prepare\_change?()](Ash.Type.String.html#prepare_change?/0) # [](Ash.Type.String.html#functions)Functions [](Ash.Type.String.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/string.ex#L1) [](Ash.Type.String.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/string.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Struct (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/struct.ex#L1 "View Source") Represents a struct. Use the `instance_of` constraint to specify that it must be an instance of a specific struct. This cannot be loaded from a database unless the `instance_of` constraint is provided. If not, it can only be used to cast input, i.e for arguments. ## [](Ash.Type.Struct.html#module-constraints)Constraints - `:instance_of` ([`atom/0`](../elixir/typespecs.html#basic-types)) - The module the struct should be an instance of - `:preserve_nil_values?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - If set to true, when storing, nil values will be kept. Otherwise, nil values will be omitted. The default value is `false`. - `:fields` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - The types of the fields in the struct, and their constraints. For example: ``` fields: [ amount: [ type: :integer, constraints: [ max: 10 ] ], currency: [ type: :string, allow_nil?: false, constraints: [ max_length: 3 ] ] ] ``` allow\_nil? is true by default - `:type` (an [`Ash.Type`](Ash.Type.html)) - Required. - `:allow_nil?` ([`boolean/0`](../elixir/typespecs.html#built-in-types)) - The default value is `true`. - `:constraints` ([`keyword/0`](../elixir/typespecs.html#built-in-types)) - The default value is `[]`. # [](Ash.Type.Struct.html#summary)Summary ## [Functions](Ash.Type.Struct.html#functions) [handle\_change?()](Ash.Type.Struct.html#handle_change?/0) [prepare\_change?()](Ash.Type.Struct.html#prepare_change?/0) # [](Ash.Type.Struct.html#functions)Functions [](Ash.Type.Struct.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/struct.ex#L1) [](Ash.Type.Struct.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/struct.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Term (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/term.ex#L1 "View Source") Represents a raw elixir term in the database A builtin type that can be referenced via `:binary` # [](Ash.Type.Term.html#summary)Summary ## [Functions](Ash.Type.Term.html#functions) [handle\_change?()](Ash.Type.Term.html#handle_change?/0) [prepare\_change?()](Ash.Type.Term.html#prepare_change?/0) # [](Ash.Type.Term.html#functions)Functions [](Ash.Type.Term.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/term.ex#L1) [](Ash.Type.Term.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/term.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Time (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/time.ex#L1 "View Source") Represents a time in the database A builtin type that can be referenced via `:time` # [](Ash.Type.Time.html#summary)Summary ## [Functions](Ash.Type.Time.html#functions) [handle\_change?()](Ash.Type.Time.html#handle_change?/0) [prepare\_change?()](Ash.Type.Time.html#prepare_change?/0) # [](Ash.Type.Time.html#functions)Functions [](Ash.Type.Time.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/time.ex#L1) [](Ash.Type.Time.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/time.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Union (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/union.ex#L1 "View Source") A union between multiple types, distinguished with a tag or by attempting to validate. ## [](Ash.Type.Union.html#module-constraints)Constraints - `:storage` - How the value will be stored when persisted. `:type_and_value` will store the type and value in a map like so `{type: :type_name, value: the_value}` `:map_with_tag` will store the value directly. This only works if all types have a `tag` and `tag_value` configured. Valid values are :type\_and\_value, :map\_with\_tag The default value is `:type_and_value`. - `:types` - The types to be unioned, a map of an identifier for the enum value to its configuration. When using `tag` and `tag_value` we are referring to a map key that must equal a certain value in order for the value to be considered an instance of that type. For example: ``` types: [ int: [ type: :integer, constraints: [ max: 10 ] ], object: [ type: MyObjectType, # The default value is `true` # this passes the tag key/value to the nested type # when casting input cast_tag?: true, tag: :type, tag_value: "my_object" ], other_object: [ type: MyOtherObjectType, cast_tag?: true, tag: :type, tag_value: "my_other_object" ], other_object_without_type: [ type: MyOtherObjectTypeWithoutType, cast_tag?: false, tag: :type, tag_value: nil ] ] ``` IMPORTANT: This is stored as a map under the hood. Filters over the data will need to take this into account. Additionally, if you are not using a tag, a value will be considered to be of the given type if it successfully casts. This means that, for example, if you try to cast `"10"` as a union of a string and an integer, it will end up as `"10"` because it is a string. If you put the integer type ahead of the string type, it will cast first and `10` will be the value. # [](Ash.Type.Union.html#summary)Summary ## [Functions](Ash.Type.Union.html#functions) [handle\_change?()](Ash.Type.Union.html#handle_change?/0) [prepare\_change?()](Ash.Type.Union.html#prepare_change?/0) # [](Ash.Type.Union.html#functions)Functions [](Ash.Type.Union.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/union.ex#L1) [](Ash.Type.Union.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/union.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.UrlEncodedBinary (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/url_encoded_binary.ex#L1 "View Source") Represents a binary that attempts to decode input strings as a url encoded base64 string. A builtin type that can be referenced via `:url_encoded_binary` # [](Ash.Type.UrlEncodedBinary.html#summary)Summary ## [Functions](Ash.Type.UrlEncodedBinary.html#functions) [handle\_change?()](Ash.Type.UrlEncodedBinary.html#handle_change?/0) [prepare\_change?()](Ash.Type.UrlEncodedBinary.html#prepare_change?/0) # [](Ash.Type.UrlEncodedBinary.html#functions)Functions [](Ash.Type.UrlEncodedBinary.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/url_encoded_binary.ex#L1) [](Ash.Type.UrlEncodedBinary.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/url_encoded_binary.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.UtcDatetime (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/utc_datetime.ex#L1 "View Source") Represents a utc datetime. A wrapper around `:datetime` for backwards compatibility. # [](Ash.Type.UtcDatetime.html#summary)Summary ## [Functions](Ash.Type.UtcDatetime.html#functions) [handle\_change?()](Ash.Type.UtcDatetime.html#handle_change?/0) [prepare\_change?()](Ash.Type.UtcDatetime.html#prepare_change?/0) # [](Ash.Type.UtcDatetime.html#functions)Functions [](Ash.Type.UtcDatetime.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/utc_datetime.ex#L1) [](Ash.Type.UtcDatetime.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/utc_datetime.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.UtcDatetimeUsec (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/utc_datetime_usec.ex#L1 "View Source") Represents a utc datetime with `nanosecond` precision. A wrapper around `:datetime` for backwards compatibility. # [](Ash.Type.UtcDatetimeUsec.html#summary)Summary ## [Functions](Ash.Type.UtcDatetimeUsec.html#functions) [handle\_change?()](Ash.Type.UtcDatetimeUsec.html#handle_change?/0) [prepare\_change?()](Ash.Type.UtcDatetimeUsec.html#prepare_change?/0) # [](Ash.Type.UtcDatetimeUsec.html#functions)Functions [](Ash.Type.UtcDatetimeUsec.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/utc_datetime_usec.ex#L1) [](Ash.Type.UtcDatetimeUsec.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/utc_datetime_usec.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.UUID (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/uuid.ex#L1 "View Source") Represents a UUID. A builtin type that can be referenced via `:uuid` # [](Ash.Type.UUID.html#summary)Summary ## [Functions](Ash.Type.UUID.html#functions) [handle\_change?()](Ash.Type.UUID.html#handle_change?/0) [prepare\_change?()](Ash.Type.UUID.html#prepare_change?/0) # [](Ash.Type.UUID.html#functions)Functions [](Ash.Type.UUID.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/uuid.ex#L1) [](Ash.Type.UUID.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/uuid.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.UUIDv7 (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/uuid_v7.ex#L1 "View Source") Represents a UUID. A builtin type that can be referenced via `:uuid_v7` # [](Ash.Type.UUIDv7.html#summary)Summary ## [Functions](Ash.Type.UUIDv7.html#functions) [handle\_change?()](Ash.Type.UUIDv7.html#handle_change?/0) [prepare\_change?()](Ash.Type.UUIDv7.html#prepare_change?/0) # [](Ash.Type.UUIDv7.html#functions)Functions [](Ash.Type.UUIDv7.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/uuid_v7.ex#L1) [](Ash.Type.UUIDv7.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/uuid_v7.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Type.Vector (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/vector.ex#L1 "View Source") Represents a vector. A builtin type that can be referenced via `:vector` # [](Ash.Type.Vector.html#summary)Summary ## [Functions](Ash.Type.Vector.html#functions) [handle\_change?()](Ash.Type.Vector.html#handle_change?/0) [prepare\_change?()](Ash.Type.Vector.html#prepare_change?/0) # [](Ash.Type.Vector.html#functions)Functions [](Ash.Type.Vector.html#handle_change?/0) # handle\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/vector.ex#L1) [](Ash.Type.Vector.html#prepare_change?/0) # prepare\_change?() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/vector.ex#L1) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Union (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/union.ex#L1 "View Source") A wrapper for values that are sourced from [`Ash.Type.Union`](Ash.Type.Union.html). # [](Ash.Union.html#summary)Summary ## [Types](Ash.Union.html#types) [t()](Ash.Union.html#t:t/0) # [](Ash.Union.html#types)Types [](Ash.Union.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/union.ex#L6) ``` @type t() :: %Ash.Union{type: term(), value: term()} ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.UUID (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid.ex#L1 "View Source") Helpers for working with UUIDs # [](Ash.UUID.html#summary)Summary ## [Functions](Ash.UUID.html#functions) [generate()](Ash.UUID.html#generate/0) Generates a new uuid # [](Ash.UUID.html#functions)Functions [](Ash.UUID.html#generate/0) # generate() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid.ex#L6) ``` @spec generate() :: Ecto.UUID.t() ``` Generates a new uuid [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.UUIDv7 (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L1 "View Source") Helpers for working with UUIDs version 7. [RFC 9562](https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-7) Used for generating UUIDs version 7 with increased clock precision for better monotonicity, as described by method 3 of the \[Section 6.2]([https://www.rfc-editor.org/rfc/rfc9562#name-monotonicity-and-counters](https://www.rfc-editor.org/rfc/rfc9562#name-monotonicity-and-counters) Inspired by the work of [Ryan Winchester](https://github.com/ryanwinchester/) on [uuidv7](https://github.com/ryanwinchester/uuidv7) ## [](Ash.UUIDv7.html#module-examples)Examples ``` iex> UUIDv7.generate() "018e90d8-06e8-7f9f-bfd7-6730ba98a51b" iex> UUIDv7.bingenerate() <<1, 142, 144, 216, 6, 232, 127, 159, 191, 215, 103, 48, 186, 152, 165, 27>> ``` # [](Ash.UUIDv7.html#summary)Summary ## [Types](Ash.UUIDv7.html#types) [raw()](Ash.UUIDv7.html#t:raw/0) A raw binary representation of a UUID. [t()](Ash.UUIDv7.html#t:t/0) A hex-encoded UUID string. ## [Functions](Ash.UUIDv7.html#functions) [bingenerate()](Ash.UUIDv7.html#bingenerate/0) Generates a version 7 UUID in the binary format. [decode(raw\_uuid)](Ash.UUIDv7.html#decode/1) Decode a string representation of a UUID to the raw binary version. [encode(hex\_uuid)](Ash.UUIDv7.html#encode/1) Encode a raw UUID to the string representation. [extract\_timestamp(uuid)](Ash.UUIDv7.html#extract_timestamp/1) Extract the millisecond timestamp from the UUID. [generate()](Ash.UUIDv7.html#generate/0) Generates a version 7 UUID using submilliseconds for increased clock precision. # [](Ash.UUIDv7.html#types)Types [](Ash.UUIDv7.html#t:raw/0) # raw() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L30) ``` @type raw() :: <<_::128>> ``` A raw binary representation of a UUID. [](Ash.UUIDv7.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L25) ``` @type t() :: <<_::288>> ``` A hex-encoded UUID string. # [](Ash.UUIDv7.html#functions)Functions [](Ash.UUIDv7.html#bingenerate/0) # bingenerate() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L57) ``` @spec bingenerate() :: raw() ``` Generates a version 7 UUID in the binary format. ## [](Ash.UUIDv7.html#bingenerate/0-example)Example ``` iex> UUIDv7.bingenerate() <<1, 142, 144, 216, 6, 232, 127, 159, 191, 215, 103, 48, 186, 152, 165, 27>> ``` [](Ash.UUIDv7.html#decode/1) # decode(raw\_uuid) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L148) ``` @spec decode(t() | raw()) :: raw() | :error ``` Decode a string representation of a UUID to the raw binary version. ## [](Ash.UUIDv7.html#decode/1-example)Example ``` iex> UUIDv7.decode("018e90d8-06e8-7f9f-bfd7-6730ba98a51b") <<1, 142, 144, 216, 6, 232, 127, 159, 191, 215, 103, 48, 186, 152, 165, 27>> ``` [](Ash.UUIDv7.html#encode/1) # encode(hex\_uuid) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L101) ``` @spec encode(t() | raw()) :: t() | :error ``` Encode a raw UUID to the string representation. ## [](Ash.UUIDv7.html#encode/1-example)Example ``` iex> UUIDv7.encode(<<1, 142, 144, 216, 6, 232, 127, 159, 191, 215, 103, 48, 186, 152, 165, 27>>) "018e90d8-06e8-7f9f-bfd7-6730ba98a51b" ``` [](Ash.UUIDv7.html#extract_timestamp/1) # extract\_timestamp(uuid) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L85) ``` @spec extract_timestamp(t() | raw()) :: integer() ``` Extract the millisecond timestamp from the UUID. ## [](Ash.UUIDv7.html#extract_timestamp/1-example)Example ``` iex> UUIDv7.extract_timestamp("018ecb40-c457-73e6-a400-000398daddd9") 1712807003223 ``` [](Ash.UUIDv7.html#generate/0) # generate() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/uuid_v7.ex#L45) ``` @spec generate() :: t() ``` Generates a version 7 UUID using submilliseconds for increased clock precision. ## [](Ash.UUIDv7.html#generate/0-example)Example ``` iex> UUIDv7.generate() "018e90d8-06e8-7f9f-bfd7-6730ba98a51b" ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Vector (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/vector.ex#L1 "View Source") A vector struct for Ash. Implementation based off of [https://github.com/pgvector/pgvector-elixir/blob/v0.2.0/lib/pgvector.ex](https://github.com/pgvector/pgvector-elixir/blob/v0.2.0/lib/pgvector.ex) # [](Ash.Vector.html#summary)Summary ## [Types](Ash.Vector.html#types) [t()](Ash.Vector.html#t:t/0) ## [Functions](Ash.Vector.html#functions) [from\_binary(binary)](Ash.Vector.html#from_binary/1) Creates a new vector from its binary representation [new(vector)](Ash.Vector.html#new/1) Creates a new vector from a list or tensor [to\_binary(vector)](Ash.Vector.html#to_binary/1) Converts the vector to its binary representation [to\_list(vector)](Ash.Vector.html#to_list/1) Converts the vector to a list # [](Ash.Vector.html#types)Types [](Ash.Vector.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/vector.ex#L10) ``` @type t() :: %Ash.Vector{data: binary()} ``` # [](Ash.Vector.html#functions)Functions [](Ash.Vector.html#from_binary/1) # from\_binary(binary) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/vector.ex#L36) ``` @spec from_binary(binary()) :: t() ``` Creates a new vector from its binary representation [](Ash.Vector.html#new/1) # new(vector) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/vector.ex#L18) ``` @spec new(t() | binary() | [integer()]) :: {:ok, t()} | {:error, :invalid_vector} ``` Creates a new vector from a list or tensor [](Ash.Vector.html#to_binary/1) # to\_binary(vector) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/vector.ex#L44) ``` @spec to_binary(t()) :: binary() ``` Converts the vector to its binary representation [](Ash.Vector.html#to_list/1) # to\_list(vector) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/vector.ex#L52) ``` @spec to_list(t()) :: list() ``` Converts the vector to a list [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Attributes [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/attributes.md#L1 "View Source") Attributes specify the `name`, `type` and additional configuration of a simple property of a record. When using SQL data layers, for example, an attribute would correspond to a column in a database table. For information on types, see [`Ash.Type`](Ash.Type.html). To see all of the options available when building attributes, see `Ash.Resource.Dsl.attributes.attribute` If you are looking to compute values on demand, see the [Calculations guide](calculations.html) and the [aggregates guide](aggregates.html). ## [](attributes.html#special-attributes)Special attributes In Ash there are 4 special attributes these are: - `create_timestamp` - `update_timestamp` - `integer_primary_key` - `uuid_primary_key` These are really just shorthand for an attribute with specific options set. They're outlined below. ### [](attributes.html#create_timestamp)`create_timestamp` You may recognise this if you have used Ecto before. This attribute will record the time at which each row is created, by default it uses [`DateTime.utc_now/1`](../elixir/DateTime.html#utc_now/1). `create_timestamp :inserted_at` is equivalent to an attribute with these options: ``` attribute :inserted_at, :utc_datetime_usec do writable? false default &DateTime.utc_now/0 match_other_defaults? true allow_nil? false end ``` ### [](attributes.html#update_timestamp)`update_timestamp` This is also similar in Ecto. This attribute records the last time a row was updated, also using [`DateTime.utc_now/1`](../elixir/DateTime.html#utc_now/1) by default. `update_timestamp :updated_at` is equivalent to: ``` attribute :updated_at, :utc_datetime_usec do writable? false default &DateTime.utc_now/0 update_default &DateTime.utc_now/0 match_other_defaults? true allow_nil? false end ``` ### [](attributes.html#uuid_primary_key)`uuid_primary_key` This attribute is used in almost every resource. It generates a UUID every time a new record is made. `uuid_primary_key :id` is equivalent to: ``` attribute :id, :uuid do writable? false default &Ash.UUID.generate/0 primary_key? true allow_nil? false end ``` ### [](attributes.html#integer_primary_key)`integer_primary_key` Creates a generated integer primary key. Keep in mind that not all data layers support auto incrementing ids, but for SQL data layers this is a very common practice. For those that don't, it is your own job to provide values for the primary key. We generally suggest using UUIDs over integers, as there are [a lot of good reasons to not use autoincrementing integer ids](https://www.clever-cloud.com/blog/engineering/2015/05/20/why-auto-increment-is-a-terrible-idea/). `integer_primary_key :id` is equivalent to: ``` attribute :id, :integer do writable? false generated? true primary_key? true allow_nil? false end ``` [← Previous Page Domains](domains.html) [Next Page → Relationships](relationships.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/attributes.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Authorize Access to Resources [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/how-to/authorize-access-to-resources.livemd#L1 "View Source") [![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](authorize-access-to-resources.html) ``` Mix.install( [ {:ash, "~> 3.0"}, {:simple_sat, "~> 0.1"}, {:kino, "~> 0.12"} ], consolidate_protocols: false ) Logger.configure(level: :warning) Application.put_env(:ash, :policies, show_policy_breakdowns?: true) ``` ## [](authorize-access-to-resources.html#introduction)Introduction A key feature of Ash is the ability to build security directly into your resources. We do this with policies. Because how you write policies is *extremely* situational, this how-to guide provides a list of "considerations" as opposed to "instructions". For more context, read the [policies guide](policies.html#policies). ## [](authorize-access-to-resources.html#writing-policies)Writing Policies 1. Consider whether or not you want to adopt a specific style of authorization, like [ACL](https://en.wikipedia.org/wiki/Access-control_list), or [RBAC](https://en.wikipedia.org/wiki/Role-based_access_control). For standard RBAC, look into [AshRbac](../ash_rbac/getting_started.html), and you may not need to write any of your own policies at that point 2. Determine if there are any `bypass` policies to add (admin users, super users, etc.). Consider placing this on the domain, instead of the resource 3. Begin by making an inventory of each action on your resource, and under what conditions a given actor may be allowed to perform them. If all actions of a given type have the same criteria, we will typically use the `action_type(:type)` condition 4. Armed with this inventory, begin to write policies. Start simple, write a policy per action type, and add a description of what your policy accomplishes. 5. Find patterns, like cross-cutting checks that exist in all policies, that can be expressed as smaller, simpler policies 6. Determine if any field policies are required to prohibit access to attributes/calculations/aggregates 7. Finally, you can confirm your understanding of the authorization flow for a given resource by generating policy charts with [`mix ash.generate_policy_charts`](Mix.Tasks.Ash.GeneratePolicyCharts.html) (field policies are not currently included in the generated charts) ## [](authorize-access-to-resources.html#example)Example ``` defmodule User do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets actions do defaults [:read, create: [:admin?]] end attributes do uuid_primary_key :id attribute :admin?, :boolean do allow_nil? false default false end end end defmodule Tweet do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets, authorizers: [Ash.Policy.Authorizer] attributes do uuid_primary_key :id attribute :text, :string do allow_nil? false constraints max_length: 144 public? true end attribute :hidden?, :boolean do allow_nil? false default false public? true end attribute :private_note, :string do sensitive? true public? true end end calculations do calculate :tweet_length, :integer, expr(string_length(text)) do public? true end end relationships do belongs_to :user, User, allow_nil?: false end actions do defaults [:read, update: [:text, :hidden?, :private_note]] create :create do primary? true accept [:text, :hidden?, :private_note] change relate_actor(:user) end end policies do # action_type-based policies policy action_type(:read) do # each policy has a description description "If a tweet is hidden, only the author can read it. Otherwise, anyone can." # first check this. If true, then this policy passes authorize_if relates_to_actor_via(:user) # then check this. If false, then this policy fails forbid_if expr(hidden? == true) # otherwise, this policy passes authorize_if always() end # blanket allow-listing of creates policy action_type(:create) do description "Anyone can create a tweet" authorize_if always() end policy action_type(:update) do description "Only an admin or the user who tweeted can edit their tweet" # first check this. If true, then this policy passes authorize_if actor_attribute_equals(:admin?, true) # then check this. If true, then this policy passes authorize_if relates_to_actor_via(:user) # otherwise, there is nothing left to check and no decision, so *this policy fails* end end field_policies do # anyone can see these fields field_policy [:text, :tweet_length] do description "Public tweet fields are visible" authorize_if always() end field_policy [:hidden?, :private_note] do description "hidden? and private_note are only visible to the author" authorize_if relates_to_actor_via(:user) end end end defmodule Domain do use Ash.Domain, validate_config_inclusion?: false resources do resource Tweet do define :create_tweet, action: :create, args: [:text] define :update_tweet, action: :update, args: [:text] define :list_tweets, action: :read define :get_tweet, action: :read, get_by: [:id] end resource User do define :create_user, action: :create end end end ``` ``` {:module, Domain, <<70, 79, 82, 49, 0, 2, 117, ...>>, [ Ash.Domain.Dsl.Resources.Resource, Ash.Domain.Dsl.Resources.Options, Ash.Domain.Dsl, %{opts: [], entities: [...]}, Ash.Domain.Dsl, Ash.Domain.Dsl.Resources.Options, ... ]} ``` ## [](authorize-access-to-resources.html#interacting-with-resources-that-have-policies)Interacting with resources that have policies ``` # doing forbidden things produces an `Ash.Error.Forbidden` user = Domain.create_user!() other_user = Domain.create_user!() tweet = Domain.create_tweet!("hello world!", actor: user) Domain.update_tweet!(tweet, "Goodbye world", actor: other_user) ``` ``` # Reading data applies policies as filters user = Domain.create_user!() other_user = Domain.create_user!() my_hidden_tweet = Domain.create_tweet!("hello world!", %{hidden?: true}, actor: user) other_users_hidden_tweet = Domain.create_tweet!("hello world!", %{hidden?: true}, actor: other_user) my_tweet = Domain.create_tweet!("hello world!", actor: user) other_users_tweet = Domain.create_tweet!("hello world!", actor: other_user) tweet_ids = Domain.list_tweets!(actor: user) |> Enum.map(& &1.id) # I see my own hidden tweets, and other users non-hidden tweets true = my_hidden_tweet.id in tweet_ids true = other_users_tweet.id in tweet_ids # but not other users hidden tweets false = other_users_hidden_tweet.id in tweet_ids :ok ``` ``` :ok ``` ``` # Field policies return hidden fields as `%Ash.ForbiddenField{}` user = Domain.create_user!() other_user = Domain.create_user!() other_users_tweet = Domain.create_tweet!("hello world!", %{private_note: "you can't see this!"}, actor: other_user) %Ash.ForbiddenField{} = Domain.get_tweet!(other_users_tweet.id, actor: user).private_note ``` ``` #Ash.ForbiddenField<field: :private_note, type: :attribute, ...> ``` ``` Tweet |> Ash.Policy.Chart.Mermaid.chart() |> Kino.Shorts.mermaid() ``` ``` flowchart TB subgraph at least one policy applies direction TB at_least_one_policy["action.type == :read or action.type == :create or action.type == :update"] end at_least_one_policy--False-->Forbidden at_least_one_policy--True-->0_conditions subgraph Policy 1[If a tweet is hidden, only the author can read it. Otherwise, anyone can.] direction TB 0_conditions{"action.type == :read"} 0_checks_0{"record.user == actor"} 0_checks_1{"hidden? == true"} end 0_conditions--True-->0_checks_0 0_conditions--False-->1_conditions 0_checks_0--True-->1_conditions 0_checks_0--False-->0_checks_1 0_checks_1--True-->Forbidden 0_checks_1--False-->1_conditions subgraph Policy 2[Anyone can create a tweet] direction TB 1_conditions{"action.type == :create"} end subgraph Policy 3[Only an admin or the user who tweeted can edit their tweet] direction TB 2_conditions{"action.type == :update"} 2_checks_0{"actor.admin? == true"} 2_checks_1{"record.user == actor"} end 2_conditions--True-->2_checks_0 2_conditions--False-->Authorized 2_checks_0--True-->Authorized 2_checks_0--False-->2_checks_1 2_checks_1--True-->Authorized 2_checks_1--False-->Forbidden subgraph results[Results] Authorized([Authorized]) Forbidden([Forbidden]) end 1_conditions--Or-->2_conditions ``` [← Previous Page Test Resources](test-resources.html) [Next Page → Encrypt Attributes](encrypt-attributes.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/how-to/authorize-access-to-resources.livemd)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Calculations [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/calculations.md#L1 "View Source") Calculations in Ash allow for displaying complex values as a top level value of a resource. ## [](calculations.html#primer)Primer ## [](calculations.html#declaring-calculations-on-a-resource)Declaring calculations on a resource ### [](calculations.html#expression-calculations)Expression Calculations The simplest kind of calculation refers to an Ash expression. For example: ``` calculations do calculate :full_name, :string, expr(first_name <> " " <> last_name) end ``` See the [Expressions guide](expressions.html) for more. ### [](calculations.html#module-calculations)Module Calculations When calculations require more complex code or can't be pushed down into the data layer, a module that uses [`Ash.Resource.Calculation`](Ash.Resource.Calculation.html) can be used. ``` defmodule Concat do # An example concatenation calculation, that accepts the delimiter as an argument, #and the fields to concatenate as options use Ash.Resource.Calculation # Optional callback that verifies the passed in options (and optionally transforms them) @impl true def init(opts) do if opts[:keys] && is_list(opts[:keys]) && Enum.all?(opts[:keys], &is_atom/1) do {:ok, opts} else {:error, "Expected a `keys` option for which keys to concat"} end end @impl true # A callback to tell Ash what keys must be loaded/selected when running this calculation # you can include related data here, but be sure to include the attributes you need from said related data # i.e `posts: [:title, :body]`. def load(_query, opts, _context) do opts[:keys] end @impl true def calculate(records, opts, %{arguments: %{separator: separator}}) do Enum.map(records, fn record -> Enum.map_join(opts[:keys], separator, fn key -> to_string(Map.get(record, key)) end) end) end # You can implement this callback to make this calculation possible in the data layer # *and* in elixir. Ash expressions are already executable in Elixir or in the data layer, but this gives you fine grain control over how it is done # @impl true # def expression(opts, context) do # end end # Usage in a resource calculations do calculate :full_name, :string, {Concat, keys: [:first_name, :last_name]} do # You need to use the [allow_empty?: true, trim?: false] constraints here. # The separator could be an empty string or require a leading or trailing space, # but would be trimmed or even set to `nil` without the constraints shown below. argument :separator, :string do allow_nil? false constraints [allow_empty?: true, trim?: false] default "" end end end ``` See the documentation for the calculations section in [Resource DSL docs](dsl-ash-resource.html#calculations) and the [`Ash.Resource.Calculation`](Ash.Resource.Calculation.html) docs for more information. The calculations declared on a resource allow for declaring a set of named calculations that can be used by extensions. They can also be loaded in the query using [`Ash.Query.load/2`](Ash.Query.html#load/2), or after the fact using [`Ash.load/3`](Ash.html#load/3). Calculations declared on the resource will be keys in the resource's struct. ## [](calculations.html#custom-calculations-in-the-query)Custom calculations in the query Example: ``` User |> Ash.Query.calculate(:full_name, {Concat, keys: [:first_name, :last_name]}, :string, %{separator: ","}) ``` See the documentation for [`Ash.Query.calculate/4`](Ash.Query.html#calculate/4) for more information. ## [](calculations.html#arguments-in-calculations)Arguments in calculations Using the above example with arguments, you can load a calculation with arguments like so: ``` load(full_name: [separator: ","]) ``` If the calculation uses an expression, you can also filter and sort on it like so: ``` query |> Ash.Query.filter(full_name(separator: " ") == "Zach Daniel") |> Ash.Query.sort(full_name: {%{separator: " "}, :asc}) ``` [← Previous Page Relationships](relationships.html) [Next Page → Aggregates](aggregates.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/calculations.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Changes [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/changes.md#L1 "View Source") Changes are the primary way of customizing create/update/destroy action behavior. If you are familiar with [`Plug`](../plug/1.16.1/Plug.html), you can think of an [`Ash.Resource.Change`](Ash.Resource.Change.html) as the equivalent of a [`Plug`](../plug/1.16.1/Plug.html) for changesets. At its most basic, a change will take a changeset and return a new changeset. Changes can be simple, like setting or modifying an attribute value, or more complex, attaching hooks to be executed within the lifecycle of the action. ## [](changes.html#builtin-changes)Builtin Changes There are a number of builtin changes that can be used, and are automatically imported into your resources. See [`Ash.Resource.Change.Builtins`](Ash.Resource.Change.Builtins.html) for more. Some examples of usage of builtin changes ``` # set the `owner` to the current actor change relate_actor(:owner) # set `commited_at` to the current timestamp when the action is called change set_attribute(:committed_at, &DateTime.utc_now/0) # optimistic lock using the `version` attribute change optimistic_lock(:version) ``` ## [](changes.html#custom-changes)Custom Changes ``` defmodule MyApp.Changes.Slugify do use Ash.Resource.Change # transform and validate opts @impl true def init(opts) do if is_atom(opts[:attribute]) do {:ok, opts} else {:error, "attribute must be an atom!"} end end @impl true def change(changeset, opts, _context) do case Ash.Changeset.fetch_change(changeset, opts[:attribute]) do {:ok, new_value} -> slug = String.replace(new_value, ~r/\s+/, "-") Ash.Changeset.force_change_attribute(changeset, opts[:attribute], slug) :error -> changeset end end end ``` This could then be used in a resource via: ``` change {MyApp.Changes.Slugify, attribute: :foo} ``` ## [](changes.html#anonymous-function-changes)Anonymous Function Changes You can also use anonymous functions for changes. Keep in mind, these cannot be made atomic, or support batching. This is great for prototyping, but we generally recommend using a module, both for organizational purposes, and to allow adding atomic/batch behavior. ``` change fn changeset, _context -> # put your code here end ``` ## [](changes.html#where)Where The `where` can be used to perform changes conditionally. This functions by running the validations in the `where`, and if the validation returns an error, we discard the error and skip the operation. This means that even custom validations can be used in conditions. For example: ``` change {Slugify, attribute: :foo} do where [attribute_equals(:slugify, true)] end ``` ## [](changes.html#action-vs-global-changes)Action vs Global Changes You can place a change on any create, update, or destroy action. For example: ``` actions do create :create do change {Slugify, attribute: :name} end end ``` Or you can use the global changes block to apply to all actions of a given type. Where statements can be used in both cases. Use `on` to determine the types of actions the validation runs on. By default, it only runs on create and update actions. ``` changes do change {Slugify, attribute: :name} do on [:create] end end ``` The changes section allows you to add changes across multiple actions of a resource. ### [](changes.html#running-on-destroy-actions)Running on destroy actions By default, changes in the global `changes` block will run on create and update only. Many changes don't make sense in the context of destroys. To make them run on destroy, use `on: [:create, :update, :destroy]` ### [](changes.html#examples)Examples ``` changes do change relate_actor(:owner) change set_attribute(:committed_at, &DateTime.utc_now/0) change optimistic_lock(:version), on: [:create, :update, :destroy] change {Slugify, [attribute: :foo]}, on: :create end ``` ## [](changes.html#atomic-changes)Atomic Changes To make a change atomic, you have to implement the [`Ash.Resource.Change.atomic/3`](Ash.Resource.Change.html#c:atomic/3) callback. This callback returns a map of changes to attributes that should be changed atomically. We will also honor any [`Ash.Resource.Change.after_batch/3`](Ash.Resource.Change.html#c:after_batch/3) functionality to run code after atomic changes have been applied (only if `atomic/3` callback has also been defined). Note that [`Ash.Resource.Change.before_batch/3`](Ash.Resource.Change.html#c:before_batch/3) is not supported in this scenario and will be ignored. ``` defmodule MyApp.Changes.Slugify do # transform and validate opts use Ash.Resource.Change ... def atomic(changeset, opts, context) do {:atomic, %{ opts[:attribute] => expr( fragment("regexp_replace(?, ?, ?)", ^ref(opts[:attribute]), ~r/\s+/, "-") ) }} end end ``` In some cases, changes operate only on arguments or context, or otherwise can do their work regardless of atomicity. In these cases, you can make your atomic callback call the `change/3` function ``` @impl true def atomic(changeset, opts, context) do {:ok, change(changeset, opts, context)} end ``` In other cases, a change may not be necessary in a fully atomic action. For this, you can simply return `:ok` ``` @impl true def atomic(_changeset, _opts, _context) do :ok end ``` ## [](changes.html#batches)Batches Changes can support being run on batches of changesets, using the [`Ash.Resource.Change.batch_change/3`](Ash.Resource.Change.html#c:batch_change/3), [`Ash.Resource.Change.before_batch/3`](Ash.Resource.Change.html#c:before_batch/3), and [`Ash.Resource.Change.after_batch/3`](Ash.Resource.Change.html#c:after_batch/3) callbacks. ### [](changes.html#when-do-we-use-batch-callbacks)When do we use batch callbacks? [`Ash.Resource.Change.batch_change/3`](Ash.Resource.Change.html#c:batch_change/3) must be defined for [`Ash.Resource.Change.before_batch/3`](Ash.Resource.Change.html#c:before_batch/3) and [`Ash.Resource.Change.after_batch/3`](Ash.Resource.Change.html#c:after_batch/3) to be called! The one exception is that `after_batch/3` is called after atomic changes as well as batches, so it will be called in cases that `atomic/3` is defined. `before_batch/3` is ignored when calling changes atomically. For some changes, this may not be necessary at all, i.e the `Slugify` example has no benefit from batching. If no batch callbacks are added, your change will be run on a loop over the changesets. For the sake of example, however, we will show what it might look like to implement batching for our `Slugify` example. ``` defmodule MyApp.Changes.Slugify do # transform and validate opts use Ash.Resource.Change @impl true def init(opts) do if is_atom(opts[:attribute]) do {:ok, opts} else {:error, "attribute must be an atom!"} end end @impl true def batch_change(changeset, opts, context) do # here we could run queries or do common work required # for a given batch of changesets. # in this example, however, we just return the changesets with # the change logic applied. Enum.map(changesets, &change(&1, opts, context)) end end ``` [← Previous Page Validations](validations.html) [Next Page → Preparations](preparations.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/changes.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Code Interface [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/code-interfaces.md#L1 "View Source") One of the ways that we interact with our resources is via hand-written code. The general pattern for that looks like building a query or a changeset for a given action, and calling it via functions like [`Ash.read/2`](Ash.html#read/2) and [`Ash.create/2`](Ash.html#create/2). This, however, is just one way to use Ash, and is designed to help you build tools that work with resources, and to power things like `AshPhoenix.Form`, `AshGraphql.Resource` and `AshJsonApi.Resource`. When working with your resources in code, we generally want something more idiomatic and simple. For example, on a domain called `Helpdesk.Support`. ``` resources do resource Ticket do define :open_ticket, args: [:subject], action: :open end end ``` This simple setup now allows you to open a ticket with `Helpdesk.Support.open_ticket(subject)`. You can cause it to raise errors instead of return them with `Helpdesk.Support.open_ticket!(subject)`. For information on the options and additional inputs these defined functions take, look at the generated function documentation, which you can do in iex with `h Helpdesk.Support.open_ticket`. For more information on the code interface, read the DSL documentation: `Ash.Domain.Dsl.resource.interfaces`. ## [](code-interfaces.html#code-interfaces-on-the-resource)Code interfaces on the resource You can define a code interface on individual resources as well, using the `code_interface` block. The DSL is the same as the DSL for defining it in the `domain`. For example: ``` code_interface do # the action open can be omitted because it matches the functon name define :open, args: [:subject] end ``` These will then be called on the resource itself, i.e `Helpdesk.Support.Ticket.open(subject)`. ## [](code-interfaces.html#using-the-code-interface)Using the code interface 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. See [`Ash.Resource.Interface`](Ash.Resource.Interface.html) for valid options. 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 Accounts.register_user(username, password, [tenant: "organization_22"]) # Because the 3rd argument is a map, we use it as action input Accounts.register_user(username, password, %{key: "val"}) # When all arguments are provided it is unambiguous Accounts.register_user(username, password, %{key: "val"}, [tenant: "organization_22"]) ``` ## [](code-interfaces.html#calculations)Calculations Resource calculations can be run dynamically using [`Ash.calculate/3`](Ash.html#calculate/3), but you can also expose them using the code\_interface with `define_calculation`. For example: ``` calculations do calculate :full_name, :string, expr(first_name <> ^arg(:separator) <> last_name) do argument :separator, :string do allow_nil? false default " " end end end # in your domain resource User do define_calculation :full_name, args: [:first_name, :last_name, {:optional, :separator}] # or if you want to take a record as an argument define_calculation :full_name, args: [:_record] end ``` This could now be used like so: ``` Accounts.full_name("Jessie", "James", "-") # or with a record as an argument Accounts.full_name(user) ``` This allows for running calculations without an instance of a resource, normally done via `Ash.load(user, :full_name)` By default, configured args will be provided for any matching named reference *or* argument. This is normally fine, but in the case that you have an argument and a reference with the same name, you can specify it by supplying `{:arg, :name}` and `{:ref, :name}`. For example: ``` define_calculation :id_matches, args: [{:arg, :id}, {:ref, :id}] ``` To make arguments optional, wrap them in `{:optional, ..}`, for example: ``` define_calculation :id_matches, args: [{:arg, :id}, {:optional, {:ref, :id}}] ``` ## [](code-interfaces.html#bulk-atomic-actions)Bulk &amp; atomic actions ### [](code-interfaces.html#bulk-updates-destroys)Bulk Updates &amp; Destroys Updates support a list, stream, or query as the first argument. This allows for bulk updates. In this mode, an `%Ash.BulkResult{}` is returned. ### [](code-interfaces.html#valid-inputs)Valid inputs You cannot provide "any enumerable", only lists, streams (a function or a %Stream{}), and queries. We have to be able to distinguish the input as a bulk input and not input to the action itself. For example: ``` Post |> Ash.Query.filter(author_id == ^author_id) |> MyApp.Blog.archive_post!() # => %Ash.BulkResult{} [%Post{}, %Post{}] |> MyApp.Blog.destroy_post!() # => %Ash.BulkResult{} end ``` You can pass options to the bulk operation with the `bulk_options` option to your code interface function. ### [](code-interfaces.html#bulk-creates)Bulk Creates For bulk creates, you can provide a list or stream of inputs. In this mode also, an `%Ash.BulkResult{}` is returned. ### [](code-interfaces.html#valid-inputs-1)Valid inputs You cannot provide "any enumerable", only lists, streams (a function or a %Stream{}). We have to be able to distinguish the input as a bulk input and not input to the action itself. Any arguments on the code interface will be applied to *all* inputs given as a list, and the arguments will come first. ``` [%{title: "Post 1"}, %{title: "Post 2"}, ...] # if `:special` is an action argument, it will be applied to all inputs |> MyApp.Blog.create_post!(:special, bulk_options: [batch_size: 10]) ``` ### [](code-interfaces.html#returning-streams-from-read-actions)Returning streams from read actions The `:stream?` option allows you to return a stream to be enumerated later. For example: ``` MyApp.Blog.my_posts(stream?: true, actor: me) # => #Stream<...> ``` [← Previous Page Preparations](preparations.html) [Next Page → Embedded Resources](embedded-resources.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/code-interfaces.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable protocol (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comparable.ex#L2 "View Source") Protocol which describes ordering relation for pair of types # [](Comparable.html#summary)Summary ## [Types](Comparable.html#types) [ord()](Comparable.html#t:ord/0) [t()](Comparable.html#t:t/0) ## [Functions](Comparable.html#functions) [compare(left\_and\_right)](Comparable.html#compare/1) Accepts struct with fields :left and :right and returns ord value # [](Comparable.html#types)Types [](Comparable.html#t:ord/0) # ord() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comparable.ex#L8) ``` @type ord() :: :gt | :lt | :eq ``` [](Comparable.html#t:t/0) # t() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comparable.ex#L7) ``` @type t() :: t() ``` # [](Comparable.html#functions)Functions [](Comparable.html#compare/1) # compare(left\_and\_right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comparable.ex#L14) ``` @spec compare(t()) :: ord() ``` Accepts struct with fields :left and :right and returns ord value [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Any.To.Any (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/defaults.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Ash.CiString.To.Ash.CiString (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Ash.CiString.To.BitString (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Atom.To.BitString (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/atom.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.BitString.To.Ash.CiString (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/ci_string.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.BitString.To.Atom (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/atom.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.BitString.To.Decimal (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.DateTime.To.DateTime (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/datetime.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Date.To.Date (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/date.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Decimal.To.BitString (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Decimal.To.Decimal (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Decimal.To.Float (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Decimal.To.Integer (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Float.To.Decimal (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Integer.To.Decimal (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/decimal.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.List.To.List (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/defaults.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Map.To.Map (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/defaults.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.NaiveDateTime.To.NaiveDateTime (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/naive_datetime.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Time.To.Time (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/ash/type/time.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comparable.Type.Tuple.To.Tuple (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/defaults.ex#L0 "View Source") [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Comp (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L2 "View Source") Provides utilities to implement and work with [`Comparable`](Comparable.html) types # [](Comp.html#summary)Summary ## [Types](Comp.html#types) [left()](Comp.html#t:left/0) [right()](Comp.html#t:right/0) ## [Functions](Comp.html#functions) [compare(left, right)](Comp.html#compare/2) Compare left and right term [defcomparable(arg1, arg2, list)](Comp.html#defcomparable/3) Helper to define ordering relation for pair of types, accepts two `term :: type` pairs and block of code where relation is described. [eq()](Comp.html#eq/0) [equal?(left, right)](Comp.html#equal?/2) Is left term equal to right term? [greater\_or\_equal?(left, right)](Comp.html#greater_or_equal?/2) Is left term greater or equal to right term? [greater\_than?(left, right)](Comp.html#greater_than?/2) Is left term greater than right term? [gt()](Comp.html#gt/0) [less\_or\_equal?(left, right)](Comp.html#less_or_equal?/2) Is left term less or equal to right term? [less\_than?(left, right)](Comp.html#less_than?/2) Is left term less than right term? [lt()](Comp.html#lt/0) [max(left, right)](Comp.html#max/2) Returns the biggest of the two given terms, if terms are equal - then the first one is returned [min(left, right)](Comp.html#min/2) Returns the smallest of the two given terms, if terms are equal - then the first one is returned [not\_equal?(left, right)](Comp.html#not_equal?/2) Is left term not equal to right term? [type\_of(v)](Comp.html#type_of/1) # [](Comp.html#types)Types [](Comp.html#t:left/0) # left() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L7) ``` @type left() :: term() ``` [](Comp.html#t:right/0) # right() [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L8) ``` @type right() :: term() ``` # [](Comp.html#functions)Functions [](Comp.html#compare/2) # compare(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L308) ``` @spec compare(left(), right()) :: Comparable.ord() ``` Compare left and right term ## [](Comp.html#compare/2-examples)Examples ``` iex> Comp.compare(1, 2) :lt iex> Comp.compare(2, 1) :gt iex> Comp.compare(1, 1) :eq ``` [](Comp.html#defcomparable/3) # defcomparable(arg1, arg2, list) (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L65) Helper to define ordering relation for pair of types, accepts two `term :: type` pairs and block of code where relation is described. ## [](Comp.html#defcomparable/3-examples)Examples ``` iex> quote do ...> use Comp ...> defmodule Foo do ...> defstruct [:value, :meta] ...> end ...> defmodule Bar do ...> defstruct [:value, :meta] ...> end ...> defcomparable %Foo{value: left} :: Foo, %Foo{value: right} :: Foo do ...> Comp.compare(left, right) ...> end ...> defcomparable %Foo{value: left} :: Foo, %Bar{value: right} :: Bar do ...> Comp.compare(left, right) ...> end ...> defcomparable %Foo{value: left} :: Foo, right :: Integer do ...> Comp.compare(left, right) ...> end ...> end ...> |> Code.compile_quoted iex> quote do ...> x = %Foo{value: 1, meta: 1} ...> y = %Foo{value: 1, meta: 2} ...> Comp.equal?(x, y) && Comp.equal?(y, x) ...> end ...> |> Code.eval_quoted ...> |> elem(0) true iex> quote do ...> x = %Foo{value: 1, meta: 1} ...> y = %Bar{value: 1, meta: 2} ...> Comp.equal?(x, y) && Comp.equal?(y, x) ...> end ...> |> Code.eval_quoted ...> |> elem(0) true iex> quote do ...> x = %Foo{value: 1, meta: 1} ...> y = 1 ...> Comp.equal?(x, y) && Comp.equal?(y, x) ...> end ...> |> Code.eval_quoted ...> |> elem(0) true ``` [](Comp.html#eq/0) # eq() (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L12) [](Comp.html#equal?/2) # equal?(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L135) ``` @spec equal?(left(), right()) :: boolean() ``` Is left term equal to right term? ## [](Comp.html#equal?/2-examples)Examples ``` iex> Comp.equal?(1, 1) true iex> Comp.equal?(1, :hello) false ``` [](Comp.html#greater_or_equal?/2) # greater\_or\_equal?(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L209) ``` @spec greater_or_equal?(left(), right()) :: boolean() ``` Is left term greater or equal to right term? ## [](Comp.html#greater_or_equal?/2-examples)Examples ``` iex> Comp.greater_or_equal?(1, 1) true iex> Comp.greater_or_equal?(1, 2) false iex> Comp.greater_or_equal?(2, 1) true ``` [](Comp.html#greater_than?/2) # greater\_than?(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L171) ``` @spec greater_than?(left(), right()) :: boolean() ``` Is left term greater than right term? ## [](Comp.html#greater_than?/2-examples)Examples ``` iex> Comp.greater_than?(1, 1) false iex> Comp.greater_than?(1, 2) false iex> Comp.greater_than?(2, 1) true ``` [](Comp.html#gt/0) # gt() (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L10) [](Comp.html#less_or_equal?/2) # less\_or\_equal?(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L228) ``` @spec less_or_equal?(left(), right()) :: boolean() ``` Is left term less or equal to right term? ## [](Comp.html#less_or_equal?/2-examples)Examples ``` iex> Comp.less_or_equal?(1, 1) true iex> Comp.less_or_equal?(1, 2) true iex> Comp.less_or_equal?(2, 1) false ``` [](Comp.html#less_than?/2) # less\_than?(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L190) ``` @spec less_than?(left(), right()) :: boolean() ``` Is left term less than right term? ## [](Comp.html#less_than?/2-examples)Examples ``` iex> Comp.less_than?(1, 1) false iex> Comp.less_than?(1, 2) true iex> Comp.less_than?(2, 1) false ``` [](Comp.html#lt/0) # lt() (macro)[](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L11) [](Comp.html#max/2) # max(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L247) ``` @spec max(left(), right()) :: left() | right() ``` Returns the biggest of the two given terms, if terms are equal - then the first one is returned ## [](Comp.html#max/2-examples)Examples ``` iex> Comp.max(1, 1) 1 iex> Comp.max(1, 2) 2 iex> Comp.max(2, 1) 2 ``` [](Comp.html#min/2) # min(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L271) ``` @spec min(left(), right()) :: left() | right() ``` Returns the smallest of the two given terms, if terms are equal - then the first one is returned ## [](Comp.html#min/2-examples)Examples ``` iex> Comp.min(1, 1) 1 iex> Comp.min(1, 2) 1 iex> Comp.min(2, 1) 1 ``` [](Comp.html#not_equal?/2) # not\_equal?(left, right) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L152) ``` @spec not_equal?(left(), right()) :: boolean() ``` Is left term not equal to right term? ## [](Comp.html#not_equal?/2-examples)Examples ``` iex> Comp.not_equal?(1, 1) false iex> Comp.not_equal?(1, :hello) true ``` [](Comp.html#type_of/1) # type\_of(v) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/comparable/comp.ex#L282) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Create Actions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/actions/create-actions.md#L1 "View Source") Create actions are used to create new records in the data layer. For example: ``` # on a ticket resource create :open do accept [:title] change set_attribute(:status, :open) end ``` Here we have a create action called `:open` that allows setting the `title`, and sets the `status` to `:open`. It could be called like so: ``` Ticket |> Ash.Changeset.for_create(:open, %{title: "Need help!"}) |> Ash.create!() ``` For a full list of all of the available options for configuring create actions, see [the Ash.Resource.Dsl documentation](dsl-ash-resource.html#actions-create). See the [Code Interface guide](code-interfaces.html) for creating an interface to call the action more elegantly, like so: ``` Support.open_ticket!("Need help!") ``` ## [](create-actions.html#bulk-creates)Bulk creates Bulk creates take a list or stream of inputs for a given action, and batches calls to the underlying data layer. Given our example above, you could call `Ash.bulk_create` like so: ``` Ash.bulk_create([%{title: "Foo"}, %{title: "Bar"}], Ticket, :open) ``` ### [](create-actions.html#check-the-docs)Check the docs! Make sure to thoroughly read and understand the documentation in [`Ash.bulk_create/4`](Ash.html#bulk_create/4) before using. Read each option and note the default values. By default, bulk creates don't return records or errors, and don't emit notifications. ## [](create-actions.html#performance)Performance Generally speaking, all regular Ash create actions are compatible (or can be made to be compatible) with bulk create actions. However, there are some important considerations. - [`Ash.Resource.Change`](Ash.Resource.Change.html) modules can be optimized for bulk actions by implementing `batch_change/3`, `before_batch/3` and `after_batch/3`. If you implement `batch_change/3`, the `change` function will no longer be called, and you should swap any behavior implemented with `before_action` and `after_action` hooks to logic in the `before_batch` and `after_batch` callbacks. - Actions that reference arguments in changes, i.e `change set_attribute(:attr, ^arg(:arg))` will prevent us from using the `batch_change/3` behavior. This is usually not a problem, for instance that change is lightweight and would not benefit from being optimized with `batch_change/3` - If your action uses `after_action` hooks, or has `after_batch/3` logic defined for any of its changes, then we *must* ask the data layer to return the records it inserted. Again, this is not generally a problem because we throw away the results of each batch by default. If you are using `return_records?: true` then you are already requesting all of the results anyway. ## [](create-actions.html#returning-a-stream)Returning a Stream Returning a stream allows you to work with a bulk action as an Elixir Stream. For example: ``` input_stream() |> Ash.bulk_create(Resource, :action, return_stream?: true, return_records?: true) |> Stream.map(fn {:ok, result} -> # process results {:error, error} -> # process errors end) |> Enum.reduce(%{}, fn {:ok, result}, acc -> # process results {:error, error} -> # process errors end) ``` ### [](create-actions.html#be-careful-with-streams)Be careful with streams Because streams are lazily evaluated, if you were to do something like this: ``` [input1, input2, ...] # has 300 things in it |> Ash.bulk_create( Resource, :action, return_stream?: true, return_records?: true, batch_size: 100 # default is 100 ) |> Enum.take(150) # stream has 300, but we only take 150 ``` What would happen is that we would insert 200 records. The stream would end after we process the first two batches of 100. Be sure you aren't using things like `Stream.take` or `Enum.take` to limit the amount of things pulled from the stream, unless you actually want to limit the number of records created. ## [](create-actions.html#upserts)Upserts Upserting is the process of "creating or updating" a record, modeled with a single simple create. Both bulk creates and regular creates support upserts. Upserts can be declared in the action, like so: ``` create :create_user do accept [:email] upsert? true upsert_identity :unique_email end ``` Or they can be done with options when calling the create action. ``` Ash.create!(changeset, upsert?: true, upsert_identity: :unique_email) ``` ### [](create-actions.html#upserts-do-not-use-an-update-action)Upserts do not use an update action While an upsert is conceptually a "create or update" operation, it does not result in an update action being called. The data layer contains the upsert implementation. This means that if you have things like global changes that are only run on update, they will not be run on upserts that result in an update. Additionally, notifications for updates will not be emitted from upserts. Most importantly, there are no *read* or *update* policies applied! You must take care that an upsert can only target records that the user has permission to update. #### Targeting Upserts Lets imagine that you want a user to upsert an article by its slug, but only if it is their article: If your action looked like this: ``` create :upsert_article_by_slug do upsert? true accept [:slug, :title, :body] upsert_identity :unique_slug end ``` and there was a different user's article with the same slug, the upsert would fail. What we must do instead is use a `filter` change to further scope the upsert: ``` create :upsert_article_by_slug do upsert? true accept [:slug, :title, :body] upsert_identity :unique_slug change filter(expr(user_id == ^actor(:id))) end ``` With this in place, the user can upsert against their *own* article's slugs, but if someone else has an article with that slug, they will get an error about slug being taken. ### [](create-actions.html#atomic-updates)Atomic Updates Upserts support atomic updates. These atomic updates *do not apply to the data being created*. They are only applied in the case of an update. For example: ``` create :create_game do accept [:identifier] upsert? true upsert_identity :identifier change set_attribute(:score, 0) change atomic_update(:score, expr(score + 1)) end ``` This will result in creating a game with a score of 0, and if the game already exists, it will increment the score by 1. For information on options configured in the action, see `Ash.Resource.Dsl.actions.create`. For information on options when calling the action, see [`Ash.create/2`](Ash.html#create/2). ## [](create-actions.html#what-happens-when-you-run-a-create-action)What happens when you run a create Action All actions are run in a transaction if the data layer supports it. You can opt out of this behavior by supplying `transaction?: false` when creating the action. When an action is being run in a transaction, all steps inside of it are serialized because transactions cannot be split across processes. - Authorization is performed on the changes - A before action hook is added to set up belongs\_to relationships that are managed. This means potentially creating/modifying the destination of the relationship, and then changing the `destination_attribute` of the relationship. - `before_transaction` and `around_transaction` hooks are called ([`Ash.Changeset.before_transaction/2`](Ash.Changeset.html#before_transaction/2)). Keep in mind, any validations that are marked as `before_action? true` (or all global validations if your action has `delay_global_validations? true`) will not have happened at this point. - A transaction is opened if the action is configured for it (by default they are) and the data layer supports transactions - `before_action` hooks are performed in order - The main action is sent to the data layer - `after_action` hooks are performed in order - Non-belongs-to relationships are managed, creating/updating/destroying related records. - The transaction is closed, if one was opened - `after_transaction` hooks are invoked with the result of the transaction (even if it was an error) [← Previous Page Read Actions](read-actions.html) [Next Page → Update Actions](update-actions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/actions/create-actions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Design Principles [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/about_ash/design-principles.md#L1 "View Source") The design principles behind Ash allows us to build an extremely flexible and powerful set of tools, without locking users into specific choices at any level. The framework acts as a spinal cord for your application, with extension points at every level to allow for custom behavior. What follows are the core tenets behind Ash Framework. ## [](design-principles.html#anything-not-everything)Anything, not Everything "Anything, not Everything" means building a framework capable of doing anything, not providing a framework that already does everything. The first is possible, the second is not. Our primary goal is to provide a framework that *unlocks* potential, and frees developers to work on the things that make their application special. To this end, there are many prebuilt extensions to use, but there is also a rich suite of tools to build your *own* extensions. In this way, you can make the framework work for you, instead of struggling to fit your application to a strictly prescribed pattern. Use as much of Ash as you can, and leverage the amazing Elixir ecosystem for everything else. ## [](design-principles.html#declarative-introspectable-derivable)Declarative, Introspectable, Derivable The real superpower behind Ash is the declarative design pattern. All behavior is driven by explicit, static declarations. A resource, for example, is really just a configuration file. On its own it does nothing. It is provided to code that reads that configuration and acts accordingly. You can read more about some simple declarative design patterns outside of the context of Ash Framework in [An Incremental Approach to Declarative Design](https://zachdaniel.dev/incremental-declarative-design). ## [](design-principles.html#configuration-over-convention)Configuration over Convention While convention has value, we believe that explicit configuration ultimately leads to more discoverable, maintainable and flexible applications than a convention driven approach. This means that we never do things like assume that files with a given name are a certain type of thing, or that because a file is in a certain location, it should perform a specific function. ## [](design-principles.html#pragmatism-first)Pragmatism First While Ash does have lofty goals and a roadmap, the priority for development is always what the *current* users of Ash need or are having trouble with. We focus on simple, pragmatic, and integrated solutions that meld well with the rest of the framework. A high priority is placed on ensuring that our users don't experience feature whip-lash due to poorly thought out implementations, and that any breaking changes (a rare occurrence) have a clean and simple upgrade path. This is something made much easier by the declarative pattern. ## [](design-principles.html#community)Community The Ash community comes together and collaborates to make sure that we can all build our software quickly, effectively and in a way that will age gracefully. We have a strict code of conduct, and love working with people of any experience level or background. To experience this first-hand, participate on [ElixirForum](https://elixirforum.com/c/elixir-framework-forums/ash-framework-forum/123) or join our [discord](https://discord.gg/D7FNG2q)! ### [](design-principles.html#domain-driven-design)Domain Driven Design? Ash is *not* a Domain Driven Design framework, if we're talking about "proper" Domain Driven Design as it is taught and discussed today. Domain Driven Design comes with a considerable amount of baggage and unnecessary complexity. While we identify with the *goals* of Domain Driven Design, we believe that a simpler approach is more effective, and that much of what DDD teaches are actually *implementation* details, and not *design* concepts. If the name wasn't taken, we would surely have claimed it for ourselves. If you must have a similar term for Ash, consider it a "Resource-oriented, Declarative Design Application Framework". [← Previous Page What is Ash?](what-is-ash.html) [Next Page → Contributing to Ash](contributing-to-ash.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/about_ash/design-principles.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Destroy Actions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/actions/destroy-actions.md#L1 "View Source") Destroy actions are comparatively simple. They expect to remove a given record, and by default return `:ok` in the successful case. Most destroy actions are one-liners, for example: ``` destroy :destroy # Can be added with the defaults defaults [:read, :destroy] ``` ## [](destroy-actions.html#soft-destroy)Soft Destroy You can mark a destroy action as `soft? true`, in which case it is handled by the [`update` action](update-actions.html) logic. For example: ``` destroy :archive do soft? true change set_attribute(:archived_at, &DateTime.utc_now/0) end ``` For a full list of all of the available options for configuring destroy actions, see [the Ash.Resource.Dsl documentation](dsl-ash-resource.html#actions-destroy). ## [](destroy-actions.html#returning-the-destroyed-record)Returning the destroyed record You can use the `return_destroyed?` option to return the destroyed record. ``` ticket = Ash.get!(Ticket, 1) Ash.destroy!(ticket) # => :ok ticket = Ash.get!(Ticket, 2) Ash.destroy!(ticket, return_destroyed?: true) # => {:ok, %Ticket{}} ``` ### [](destroy-actions.html#loading-on-destroyed-records)Loading on destroyed records Keep in mind that using `Ash.load` on destroyed data will produced mixed results. Relationships may appear as empty, or may be loaded as expected (depending on the data layer/relationship implementation) and calculations/aggregates may show as `nil` if they must be run in the data layer. ## [](destroy-actions.html#bulk-destroys)Bulk Destroys There are three strategies for bulk destroying data. They are, in order of preference: `:atomic`, `:atomic_batches`, and `:stream`. When calling [`Ash.bulk_destroy/4`](Ash.html#bulk_destroy/4), you can provide a strategy or strategies that can be used, and Ash will choose the best one available. The capabilities of the data layer determine what strategies can be used. ## [](destroy-actions.html#atomic)Atomic Atomic bulk destroys are used when the subject of the bulk destroy is a query and the data layer supports destroying a query. They map to a single statement to the data layer to destroy all matching records. ### [](destroy-actions.html#example)Example ``` Ticket |> Ash.Query.filter(status == :open) |> Ash.bulk_destroy!(:close) ``` If using a SQL data layer, this would produce a query along the lines of ``` DELETE FROM tickets WHERE status = 'open'; ``` ## [](destroy-actions.html#atomic-batches)Atomic Batches Atomic batches are used when the subject of the bulk destroy is an enumerable (i.e list or stream) of records and the data layer supports destroying a query. The records are pulled out in batches, and then each batch follows the logic described [above](destroy-actions.html#atomic). The batch size is controllable by the `batch_size` option. ### [](destroy-actions.html#example-1)Example ``` Ash.bulk_destroy!(one_hundred_tickets, :close, %{}, batch_size: 10) ``` If using a SQL data layer, this would produce ten queries along the lines of ``` DELETE FROM tickets WHERE id IN (...ids) ``` ## [](destroy-actions.html#stream)Stream Stream is used when the data layer does not support destroying a query. If a query is given, it is run and the records are used as an enumerable of inputs. If an enumerable of inputs is given, each one is destroyed individually. There is nothing inherently wrong with doing this kind of destroy, but it will naturally be slower than the other two strategies. The benefit of having a single interface ([`Ash.bulk_destroy/4`](Ash.html#bulk_destroy/4)) is that the caller doesn't need to change based on the performance implications of the action. ### [](destroy-actions.html#check-the-docs)Check the docs! Make sure to thoroughly read and understand the documentation in [`Ash.bulk_destroy/4`](Ash.html#bulk_destroy/4) before using. Read each option and note the default values. By default, bulk destroys don't return records or errors, and don't emit notifications. ### [](destroy-actions.html#destroying-records)Destroying records If you provide an enumerable of records, they will be destroyed in batches. For example: ``` Ash.bulk_destroy([%Ticket{}, %Ticket{}], :destroy) ``` ### [](destroy-actions.html#destroying)Destroying ## [](destroy-actions.html#running-the-destroy-action)Running the Destroy Action All actions are run in a transaction if the data layer supports it. You can opt out of this behavior by supplying `transaction?: false` when creating the action. When an action is being run in a transaction, all steps inside of it are serialized because transactions cannot be split across processes. - Authorization is performed on the changes - A before action hook is added to set up belongs\_to relationships that are managed. This means potentially creating/modifying the destination of the relationship, and then changing the `destination_attribute` of the relationship. - `before_transaction` and `around_transaction` hooks are called ([`Ash.Changeset.before_transaction/2`](Ash.Changeset.html#before_transaction/2)). Keep in mind, any validations that are marked as `before_action? true` (or all global validations if your action has `delay_global_validations? true`) will not have happened at this point. - A transaction is opened if the action is configured for it (by default they are) and the data layer supports transactions - `before_action` hooks are performed in order - The main action is sent to the data layer - `after_action` hooks are performed in order - Non-belongs-to relationships are managed, creating/updating/destroying related records. - The transaction is closed, if one was opened - `after_transaction` hooks are invoked with the result of the transaction (even if it was an error) [← Previous Page Update Actions](update-actions.html) [Next Page → Generic Actions](generic-actions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/actions/destroy-actions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Development Utilities [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/development/development-utilities.md#L1 "View Source") ## [](development-utilities.html#formatting-dsls)Formatting DSLs All Ash packages that ship with extensions provide exports in their `.formatter.exs`. This prevents the formatter from turning, for example, `attribute :name, :string` into `attribute(:name, :string)`. To enable this, add `:ash` (and any other Ash libraries you are using) to your `.formatter.exs` file: ``` [ # ... import_deps: [..., :ash], # ... ] ``` ## [](development-utilities.html#elixirsense-plugin)ElixirSense Plugin Ash uses [Spark](../spark.html) to build all of our DSLs (like [`Ash.Resource`](Ash.Resource.html) and [`Ash.Domain`](Ash.Domain.html)) and to validate options lists to functions. [`Spark`](../spark/2.2.40/Spark.html) ships with an extension that is automatically picked up by ElixirLS to provide autocomplete for all of our DSLs, and options list. You don't need to do anything to enable this, but it only works with ElixirLS (not other language server tools). ## [](development-utilities.html#formatter-plugin)Formatter plugin [`Spark`](../spark/2.2.40/Spark.html) also ships with a formatter plugin that can help you keep your resources formatted consistently. This plugin can sort the sections of your DSL to make your resources more consistent, and it can remove any accidentally added parentheses around DSL code. ### [](development-utilities.html#adding-the-plugin)Adding the plugin Add the following to your `.formatter.exs` ``` [ plugins: [Spark.Formatter], # <- add the plugin here inputs: ... ] ``` ### [](development-utilities.html#configuration)Configuration #### Minimal config for your Ash Resources ``` config :spark, :formatter, remove_parens?: true, "Ash.Domain": [], "Ash.Resource": [ section_order: [ # any section not in this list is left where it is # but these sections will always appear in this order in a resource :actions, :attributes, :relationships, :identities ] ] ``` #### If you `use` a different module than Ash.Resource ``` config :spark, :formatter, [ "Ash.Resource": [ section_order: [ :resource, :identities, :attributes, :relationships, ... ] ], # If you use a different module than Ash.Resource "MyApp.Resource": [ type: Ash.Resource, # What extensions might be added by your base module extensions: [...], section_order: [ :resource, :identities, :attributes, :relationships, ... ] ] ] ``` [← Previous Page Testing](testing.html) [Next Page → Upgrade](upgrading-to-3-0.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/development/development-utilities.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Domains [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/domains.md#L1 "View Source") Domains serve three primary purposes: 1. They group related resources together, providing organization and structure to your project. 2. They allow you to define a centralized [code interface](code-interfaces.html) 3. They allow you to configure certain cross-cutting concerns of those resources in a single place. If you are familiar with a [Phoenix Context](../phoenix/contexts.html), you can think of a domain as the Ash equivalent. ## [](domains.html#grouping-resources)Grouping Resources In an [`Ash.Domain`](Ash.Domain.html), you will typically see something like this: ``` defmodule MyApp.Tweets do use Ash.Domain resources do resource MyApp.Tweets.Tweet resource MyApp.Tweets.Comment end end ``` With this definition, you can do things like placing all of these resources into a GraphQL Api with AshGraphql. You'd see a line like this: ``` use AshGraphql, domains: [MyApp.Tweets] ``` ## [](domains.html#centralized-code-interface)Centralized [Code Interface](code-interfaces.html) Working with our domain &amp; resources in code *can* be done the long form way, by building changesets/queries/action inputs and calling the relevant function in [`Ash`](Ash.html). However, we generally want to expose a well defined code API for working with our resources. This makes our code much clearer, and gives us nice things like auto complete and inline documentation. ``` defmodule MyApp.Tweets do use Ash.Domain resources do resource MyApp.Tweets.Tweet do # define a function called `tweet` that uses # the `:create` action on MyApp.Tweets.Tweet define :tweet, action: :create, args: [:text] end resource MyApp.Tweets.Comment do # define a function called `comment` that uses # the `:create` action on MyApp.Tweets.Comment define :comment, action: :create, args: [:tweet_id, :text] end end end ``` With these definitions, we can now do things like this: ``` tweet = MyApp.Tweets.tweet!("My first tweet!", actor: user1) comment = MyApp.Tweets.comment!(tweet.id, "What a cool tweet!", actor: user2) ``` ## [](domains.html#configuring-cross-cutting-concerns)Configuring Cross-cutting Concerns ### [](domains.html#built-in-configuration)Built in configuration [`Ash.Domain`](Ash.Domain.html) comes with a number of built-in configuration options. See `Ash.Domain` for more. For example: ``` defmodule MyApp.Tweets do use Ash.Domain resources do resource MyApp.Tweets.Tweet resource MyApp.Tweets.Comment end execution do # raise the default timeout for all actions in this domain from 30s to 60s timeout :timer.seconds(60) end authorization do # disable using the authorize?: false flag when calling actions authorize :always end end ``` ### [](domains.html#extensions)Extensions Extensions will often come with "domain extensions" to allow you to configure the behavior of all resources within a domain, as it pertains to that extension. For example: ``` defmodule MyApp.Tweets do use Ash.Domain, extensions: [AshGraphql.Domain] graphql do # skip authorization for these resources authorize? false end resources do resource MyApp.Tweets.Tweet resource MyApp.Tweets.Comment end end ``` ### [](domains.html#policies)Policies You can also use [`Ash.Policy.Authorizer`](Ash.Policy.Authorizer.html) on your domains. This allows you to add policies that apply to *all* actions using this domain. For example: ``` defmodule MyApp.Tweets do use Ash.Domain, extensions: [Ash.Policy.Authorizer] resources do resource MyApp.Tweets.Tweet resource MyApp.Tweets.Comment end policies do # add a bypass up front to allow administrators to do whatever they want bypass actor_attribute_equals(:is_admin, true) do authorize_if always() end # forbid all access from disabled users policy actor_attribute_equals(:disabled, true) do forbid_if always() end end end ``` [← Previous Page Expressions](expressions.html) [Next Page → Attributes](attributes.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/domains.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Ets [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/dsls/DSL-Ash.DataLayer.Ets.md#L1 "View Source") An ETS (Erlang Term Storage) backed Ash Datalayer, for testing and lightweight usage. Remember, this does not have support for transactions! This is not recommended for production use, especially in multi-user applications. It can, however, be great for prototyping. ## [](dsl-ash-datalayer-ets.html#ets)ets A section for configuring the ets data layer ### [](dsl-ash-datalayer-ets.html#examples)Examples ``` ets do # Used in testing private? true end ``` ### [](dsl-ash-datalayer-ets.html#options)Options NameTypeDefaultDocs[`private?`](dsl-ash-datalayer-ets.html#ets-private?)`boolean``false`Sets the ets table protection to private, and scopes it to only this process. The table name will not be used directly if this is true, to allow multiple processes to use this resource separately.[`table`](dsl-ash-datalayer-ets.html#ets-table)`atom`The name of the table. Defaults to the resource name. [← Previous Page Ash.Policy.Authorizer](dsl-ash-policy-authorizer.html) [Next Page → Ash.DataLayer.Mnesia](dsl-ash-datalayer-mnesia.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/dsls/DSL-Ash.DataLayer.Ets.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.DataLayer.Mnesia [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/dsls/DSL-Ash.DataLayer.Mnesia.md#L1 "View Source") An Mnesia backed Ash Datalayer. In your application initialization, you will need to call `Mnesia.create_schema([node()])`. Additionally, you will want to create your mnesia tables there. This data layer is *unoptimized*, fetching all records from a table and filtering them in memory. For that reason, it is not recommended to use it with large amounts of data. It can be great for prototyping or light usage, though. ## [](dsl-ash-datalayer-mnesia.html#mnesia)mnesia A section for configuring the mnesia data layer ### [](dsl-ash-datalayer-mnesia.html#examples)Examples ``` mnesia do table :custom_table end ``` ### [](dsl-ash-datalayer-mnesia.html#options)Options NameTypeDefaultDocs[`table`](dsl-ash-datalayer-mnesia.html#mnesia-table)`atom`The table name to use, defaults to the name of the resource [← Previous Page Ash.DataLayer.Ets](dsl-ash-datalayer-ets.html) [Next Page → Ash.Reactor](dsl-ash-reactor.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/dsls/DSL-Ash.DataLayer.Mnesia.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Domain [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/dsls/DSL-Ash.Domain.md#L1 "View Source") ## [](dsl-ash-domain.html#domain)domain General domain configuration ### [](dsl-ash-domain.html#examples)Examples ``` domain do description """ Resources related to the flux capacitor. """ end ``` ### [](dsl-ash-domain.html#options)Options NameTypeDefaultDocs[`description`](dsl-ash-domain.html#domain-description)`String.t`A description for the domain. ## [](dsl-ash-domain.html#resources)resources List the resources of this domain ### [](dsl-ash-domain.html#nested-dsls)Nested DSLs - [resource](dsl-ash-domain.html#resources-resource) - define - define\_calculation ### [](dsl-ash-domain.html#examples-1)Examples ``` resources do resource MyApp.Tweet resource MyApp.Comment end ``` ### [](dsl-ash-domain.html#options-1)Options NameTypeDefaultDocs[`allow`](dsl-ash-domain.html#resources-allow)`mfa`Support a dynamic resource list by providing a callback that checks whether or not the resource should be allowed.[`allow_unregistered?`](dsl-ash-domain.html#resources-allow_unregistered?)`boolean``false`Whether the domain will support only registered entries or not. ### [](dsl-ash-domain.html#resources-resource)resources.resource ``` resource resource ``` A resource present in the domain ### [](dsl-ash-domain.html#nested-dsls-1)Nested DSLs - [define](dsl-ash-domain.html#resources-resource-define) - [define\_calculation](dsl-ash-domain.html#resources-resource-define_calculation) ### [](dsl-ash-domain.html#examples-2)Examples ``` resource Foo ``` ### [](dsl-ash-domain.html#arguments)Arguments NameTypeDefaultDocs[`resource`](dsl-ash-domain.html#resources-resource-resource)`module` ### [](dsl-ash-domain.html#resources-resource-define)resources.resource.define ``` define name ``` Defines a function with the corresponding name and arguments. See the [code interface guide](code-interfaces.html) for more. ### [](dsl-ash-domain.html#examples-3)Examples ``` define :get_user_by_id, action: :get_by_id, args: [:id], get?: true ``` ### [](dsl-ash-domain.html#arguments-1)Arguments NameTypeDefaultDocs[`name`](dsl-ash-domain.html#resources-resource-define-name)`atom`The name of the function that will be defined ### [](dsl-ash-domain.html#options-2)Options NameTypeDefaultDocs[`action`](dsl-ash-domain.html#resources-resource-define-action)`atom`The name of the action that will be called. Defaults to the same name as the function.[`args`](dsl-ash-domain.html#resources-resource-define-args)`list(atom | {:optional, atom})`Map specific arguments to named inputs. Can provide any argument/attributes that the action allows.[`not_found_error?`](dsl-ash-domain.html#resources-resource-define-not_found_error?)`boolean``true`If the action or interface is configured with `get?: true`, this determines whether or not an error is raised or `nil` is returned.[`require_reference?`](dsl-ash-domain.html#resources-resource-define-require_reference?)`boolean``true`For update and destroy actions, require a resource or identifier to be passed in as the first argument. Not relevant for other action types.[`get?`](dsl-ash-domain.html#resources-resource-define-get?)`boolean``false`Expects to only receive a single result from a read action or a bulk update/destroy, and returns a single result instead of a list. Sets `require_reference?` to false automatically.[`get_by`](dsl-ash-domain.html#resources-resource-define-get_by)`atom | list(atom)`Takes a list of fields and adds those fields as arguments, which will then be used to filter. Sets `get?` to true and `require_reference?` to false automatically. Adds filters for read, update and destroy actions, replacing the `record` first argument.[`get_by_identity`](dsl-ash-domain.html#resources-resource-define-get_by_identity)`atom`Takes an identity, gets its field list, and performs the same logic as `get_by` with those fields. Adds filters for read, update and destroy actions, replacing the `record` first argument.[`default_options`](dsl-ash-domain.html#resources-resource-define-default_options)`keyword``[]`Default options to be merged with client-provided options. These can override domain or action defaults. `:load`, `:bulk_options`, and `:page` options will be deep merged. ### [](dsl-ash-domain.html#introspection)Introspection Target: [`Ash.Resource.Interface`](Ash.Resource.Interface.html) ### [](dsl-ash-domain.html#resources-resource-define_calculation)resources.resource.define\_calculation ``` define_calculation name ``` Defines a function with the corresponding name and arguments, that evaluates a calculation. Use `:_record` to take an instance of a record. See the [code interface guide](code-interfaces.html) for more. ### [](dsl-ash-domain.html#examples-4)Examples ``` define_calculation :referral_link, User, args: [:id] ``` ``` define_calculation :referral_link, User, args: [{:arg, :id}, {:ref, :id}] ``` ### [](dsl-ash-domain.html#arguments-2)Arguments NameTypeDefaultDocs[`name`](dsl-ash-domain.html#resources-resource-define_calculation-name)`atom`The name of the function that will be defined ### [](dsl-ash-domain.html#options-3)Options NameTypeDefaultDocs[`calculation`](dsl-ash-domain.html#resources-resource-define_calculation-calculation)`atom`The name of the calculation that will be evaluated. Defaults to the same name as the function.[`args`](dsl-ash-domain.html#resources-resource-define_calculation-args)`any``[]`Supply field or argument values referenced by the calculation, in the form of :name, `{:arg, :name}` and/or `{:ref, :name}`. See the [code interface guide](code-interfaces.html) for more. ### [](dsl-ash-domain.html#introspection-1)Introspection Target: [`Ash.Resource.CalculationInterface`](Ash.Resource.CalculationInterface.html) ### [](dsl-ash-domain.html#introspection-2)Introspection Target: [`Ash.Domain.Dsl.ResourceReference`](Ash.Domain.Dsl.ResourceReference.html) ## [](dsl-ash-domain.html#execution)execution Options for how requests are executed using this domain ### [](dsl-ash-domain.html#examples-5)Examples ``` execution do timeout :timer.seconds(30) end ``` ### [](dsl-ash-domain.html#options-4)Options NameTypeDefaultDocs[`timeout`](dsl-ash-domain.html#execution-timeout)`timeout``:infinity`The default timeout in milliseconds to use for requests using this domain. See the [timeouts guide](timeouts.html) for more.[`trace_name`](dsl-ash-domain.html#execution-trace_name)`String.t`The name to use in traces. Defaults to the last part of the module. See the [monitoring guide](monitoring.html) for more ## [](dsl-ash-domain.html#authorization)authorization Options for how requests are authorized using this domain. See the [Sensitive Data guide](sensitive-data.html) for more. ### [](dsl-ash-domain.html#examples-6)Examples ``` authorization do authorize :always end ``` ### [](dsl-ash-domain.html#options-5)Options NameTypeDefaultDocs[`require_actor?`](dsl-ash-domain.html#authorization-require_actor?)`boolean``false`Requires that an actor has been supplied.[`authorize`](dsl-ash-domain.html#authorization-authorize)`:always | :by_default | :when_requested``:by_default`When to run authorization for a given request. [← Previous Page Ash.Resource](dsl-ash-resource.html) [Next Page → Ash.Notifier.PubSub](dsl-ash-notifier-pubsub.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/dsls/DSL-Ash.Domain.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Notifier.PubSub [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/dsls/DSL-Ash.Notifier.PubSub.md#L1 "View Source") A builtin notifier to help you publish events over any kind of pub-sub tooling. This is plug and play with `Phoenix.PubSub`, but could be used with any pubsub system. You configure a module that defines a `broadcast/3` function, and then add some "publications" which configure under what conditions an event should be sent and what the topic should be. ## [](dsl-ash-notifier-pubsub.html#example)Example ``` defmodule MyApp.User do use Ash.Resource, # ... notifiers: [Ash.Notifier.PubSub] # ... pub_sub do module MyAppWeb.Endpoint prefix "user" publish :update, ["updated", :_pkey] end end ``` ## [](dsl-ash-notifier-pubsub.html#debugging-pubsub)Debugging PubSub It can be quite frustrating when setting up pub\_sub when everything appears to be set up properly, but you aren't receiving events. This usually means some kind of mismatch between the event names produced by the resource/config of your publications, and you can use the following flag to display debug information about all pub sub events. ``` config :ash, :pub_sub, debug?: true ``` ## [](dsl-ash-notifier-pubsub.html#topic-templates)Topic Templates Often you want to include some piece of data in the thing being changed, like the `:id` attribute. This is done by providing a list as the topic, and using atoms which will be replaced by their corresponding values. They will ultimately be joined with `:`. For example: ``` prefix "user" publish :create, ["created", :user_id] ``` This might publish a message to "user:created:1" for example. For updates, if the field in the template is being changed, a message is sent to *both* values. So if you change `user 1` to `user 2`, the same message would be published to `user:updated:1` and `user:updated:2`. If there are multiple attributes in the template, and they are all being changed, a message is sent for every combination of substitutions. ## [](dsl-ash-notifier-pubsub.html#important)Important If the previous value was `nil` or the field was not selected on the data passed into the action, then a notification is not sent for the previous value. If the new value is `nil` then a notification is not sent for the new value. ## [](dsl-ash-notifier-pubsub.html#template-parts)Template parts Templates may contain lists, in which case all combinations of values in the list will be used. Add `nil` to the list if you want to produce a pattern where that entry is omitted. The atom `:_tenant` may be used. If the changeset has a tenant set on it, that value will be used, otherwise that combination of values is ignored. The atom `:_pkey` may be used. It will be a stringified, concatenation of the primary key fields, or just the primary key if there is only one primary key field. The atom `nil` may be used. It only makes sense to use it in the context of a list of alternatives, and adds a pattern where that part is skipped. ``` publish :updated, [[:team_id, :_tenant], "updated", [:id, nil]] ``` Would produce the following messages, given a `team_id` of 1, a `tenant` of `org_1`, and an `id` of `50`: ``` "1:updated:50" "1:updated" "org_1:updated:50" "org_1:updated" ``` ## [](dsl-ash-notifier-pubsub.html#custom-delimiters)Custom Delimiters It's possible to change the default delimiter used when generating topics. This is useful when working with message brokers like RabbitMQ, which rely on a different set of delimiters for routing. ``` pub_sub do delimiter "." end ``` ## [](dsl-ash-notifier-pubsub.html#named-pubsub-modules)Named Pubsub modules If you are using a phoenix `Endpoint` module for pubsub then this is unnecessary. If you want to use a custom pub sub started with something like `{Phoenix.PubSub, name: MyName}`, then you can provide `MyName` to here. ## [](dsl-ash-notifier-pubsub.html#broadcast-types)Broadcast Types Configured with `broadcast_type`. - `:notification` just sends the notification - `:phoenix_broadcast` sends a `%Phoenix.Socket.Broadcast{}` (see above) - `:broadcast` sends `%{topic: (topic), event: (event), notification: (notification)}` ## [](dsl-ash-notifier-pubsub.html#pub_sub)pub\_sub A section for configuring how resource actions are published over pubsub ### [](dsl-ash-notifier-pubsub.html#nested-dsls)Nested DSLs - [publish](dsl-ash-notifier-pubsub.html#pub_sub-publish) - [publish\_all](dsl-ash-notifier-pubsub.html#pub_sub-publish_all) ### [](dsl-ash-notifier-pubsub.html#examples)Examples ``` pub_sub do module MyEndpoint prefix "post" publish :destroy, ["foo", :id] publish :update, ["bar", :name] event: "name_change" publish_all :create, "created" end ``` ### [](dsl-ash-notifier-pubsub.html#options)Options NameTypeDefaultDocs[`module`](dsl-ash-notifier-pubsub.html#pub_sub-module)`atom`The module to call `broadcast/3` on e.g module.broadcast(topic, event, message).[`prefix`](dsl-ash-notifier-pubsub.html#pub_sub-prefix)`String.t`A prefix for all pubsub messages, e.g `users`. A message with `created` would be published as `users:created`[`delimiter`](dsl-ash-notifier-pubsub.html#pub_sub-delimiter)`String.t`A delimiter for building topics. Default is a colon (:)[`broadcast_type`](dsl-ash-notifier-pubsub.html#pub_sub-broadcast_type)`:notification | :phoenix_broadcast | :broadcast``:notification`What shape the event payloads will be in. See[`name`](dsl-ash-notifier-pubsub.html#pub_sub-name)`atom`A named pub sub to pass as the first argument to broadcast. ### [](dsl-ash-notifier-pubsub.html#pub_sub-publish)pub\_sub.publish ``` publish action, topic ``` Configure a given action to publish its results over a given topic. ### [](dsl-ash-notifier-pubsub.html#examples-1)Examples ``` publish :create, "created" ``` ``` publish :assign, "assigned" ``` ### [](dsl-ash-notifier-pubsub.html#arguments)Arguments NameTypeDefaultDocs[`action`](dsl-ash-notifier-pubsub.html#pub_sub-publish-action)`atom`The name of the action that should be published[`topic`](dsl-ash-notifier-pubsub.html#pub_sub-publish-topic)`any`The topic to publish ### [](dsl-ash-notifier-pubsub.html#options-1)Options NameTypeDefaultDocs[`previous_values?`](dsl-ash-notifier-pubsub.html#pub_sub-publish-previous_values?)`boolean``false`Whether or not to publish messages with both the new values and the old values for referencing changed attributes[`event`](dsl-ash-notifier-pubsub.html#pub_sub-publish-event)`String.t`The name of the event to publish. Defaults to the action name[`dispatcher`](dsl-ash-notifier-pubsub.html#pub_sub-publish-dispatcher)`atom`The module to use as a dispatcher. If none is set, the pubsub module provided is used. ### [](dsl-ash-notifier-pubsub.html#introspection)Introspection Target: [`Ash.Notifier.PubSub.Publication`](Ash.Notifier.PubSub.Publication.html) ### [](dsl-ash-notifier-pubsub.html#pub_sub-publish_all)pub\_sub.publish\_all ``` publish_all type, topic ``` Works the same as `publish`, except that it takes a type and publishes all actions of that type. ### [](dsl-ash-notifier-pubsub.html#examples-2)Examples ``` publish_all :create, "created" ``` ### [](dsl-ash-notifier-pubsub.html#arguments-1)Arguments NameTypeDefaultDocs[`type`](dsl-ash-notifier-pubsub.html#pub_sub-publish_all-type)`:create | :update | :destroy`Publish on all actions of a given type[`topic`](dsl-ash-notifier-pubsub.html#pub_sub-publish_all-topic)`any`The topic to publish ### [](dsl-ash-notifier-pubsub.html#options-2)Options NameTypeDefaultDocs[`except`](dsl-ash-notifier-pubsub.html#pub_sub-publish_all-except)`list(atom)``[]`Exclude these actions from notifications[`action`](dsl-ash-notifier-pubsub.html#pub_sub-publish_all-action)`atom`The name of the action that should be published[`previous_values?`](dsl-ash-notifier-pubsub.html#pub_sub-publish_all-previous_values?)`boolean``false`Whether or not to publish messages with both the new values and the old values for referencing changed attributes[`event`](dsl-ash-notifier-pubsub.html#pub_sub-publish_all-event)`String.t`The name of the event to publish. Defaults to the action name[`dispatcher`](dsl-ash-notifier-pubsub.html#pub_sub-publish_all-dispatcher)`atom`The module to use as a dispatcher. If none is set, the pubsub module provided is used. ### [](dsl-ash-notifier-pubsub.html#introspection-1)Introspection Target: [`Ash.Notifier.PubSub.Publication`](Ash.Notifier.PubSub.Publication.html) [← Previous Page Ash.Domain](dsl-ash-domain.html) [Next Page → Ash.Policy.Authorizer](dsl-ash-policy-authorizer.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/dsls/DSL-Ash.Notifier.PubSub.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Policy.Authorizer [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/dsls/DSL-Ash.Policy.Authorizer.md#L1 "View Source") An authorization extension for ash resources. To add this extension to a resource, add it to the list of `authorizers` like so: ``` use Ash.Resource, ..., authorizers: [ Ash.Policy.Authorizer ] ``` A resource can be given a set of policies, which are enforced on each call to a resource action. For reads, policies can be configured to filter out data that the actor shouldn't see, as opposed to resulting in a forbidden error. See the [policies guide](policies.html) for practical examples. Policies are solved/managed via a boolean satisfiability solver. To read more about boolean satisfiability, see this page: [https://en.wikipedia.org/wiki/Boolean\_satisfiability\_problem](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem). At the end of the day, however, it is not necessary to understand exactly how Ash takes your authorization requirements and determines if a request is allowed. The important thing to understand is that Ash may or may not run any/all of your authorization rules as they may be deemed unnecessary. As such, authorization checks should have no side effects. Ideally, the checks built-in to ash should cover the bulk of your needs. ## [](dsl-ash-policy-authorizer.html#policies)policies A section for declaring authorization policies. Each policy that applies must pass independently in order for the request to be authorized. See the [policies guide](policies.html) for more. ### [](dsl-ash-policy-authorizer.html#nested-dsls)Nested DSLs - [policy](dsl-ash-policy-authorizer.html#policies-policy) - authorize\_if - forbid\_if - authorize\_unless - forbid\_unless - [policy\_group](dsl-ash-policy-authorizer.html#policies-policy_group) - policy - authorize\_if - forbid\_if - authorize\_unless - forbid\_unless - [bypass](dsl-ash-policy-authorizer.html#policies-bypass) - authorize\_if - forbid\_if - authorize\_unless - forbid\_unless ### [](dsl-ash-policy-authorizer.html#examples)Examples ``` policies do # Anything you can use in a condition, you can use in a check, and vice-versa # This policy applies if the actor is a super_user # Additionally, this policy is declared as a `bypass`. That means that this check is allowed to fail without # failing the whole request, and that if this check *passes*, the entire request passes. bypass actor_attribute_equals(:super_user, true) do authorize_if always() end # This will likely be a common occurrence. Specifically, policies that apply to all read actions policy action_type(:read) do # unless the actor is an active user, forbid their request forbid_unless actor_attribute_equals(:active, true) # if the record is marked as public, authorize the request authorize_if attribute(:public, true) # if the actor is related to the data via that data's `owner` relationship, authorize the request authorize_if relates_to_actor_via(:owner) end end ``` ### [](dsl-ash-policy-authorizer.html#options)Options NameTypeDefaultDocs[`default_access_type`](dsl-ash-policy-authorizer.html#policies-default_access_type)`:strict | :filter | :runtime``:filter`The default access type of policies for this resource. ### [](dsl-ash-policy-authorizer.html#policies-policy)policies.policy ``` policy condition \\ nil ``` A policy has a name, a condition, and a list of checks. Checks apply logically in the order they are specified, from top to bottom. If no check explicitly authorizes the request, then the request is forbidden. This means that, if you want to "blacklist" instead of "whitelist", you likely want to add an `authorize_if always()` at the bottom of your policy, like so: ``` policy action_type(:read) do forbid_if not_logged_in() forbid_if user_is_denylisted() forbid_if user_is_in_denylisted_group() authorize_if always() end ``` If the policy should always run, use the `always()` check, like so: ``` policy always() do ... end ``` See the [policies guide](policies.html) for more. ### [](dsl-ash-policy-authorizer.html#nested-dsls-1)Nested DSLs - [authorize\_if](dsl-ash-policy-authorizer.html#policies-policy-authorize_if) - [forbid\_if](dsl-ash-policy-authorizer.html#policies-policy-forbid_if) - [authorize\_unless](dsl-ash-policy-authorizer.html#policies-policy-authorize_unless) - [forbid\_unless](dsl-ash-policy-authorizer.html#policies-policy-forbid_unless) ### [](dsl-ash-policy-authorizer.html#arguments)Arguments NameTypeDefaultDocs[`condition`](dsl-ash-policy-authorizer.html#policies-policy-condition)`any`A check or list of checks that must be true in order for this policy to apply. ### [](dsl-ash-policy-authorizer.html#options-1)Options NameTypeDefaultDocs[`description`](dsl-ash-policy-authorizer.html#policies-policy-description)`String.t`A description for the policy, used when explaining authorization results[`access_type`](dsl-ash-policy-authorizer.html#policies-policy-access_type)`:strict | :filter | :runtime`Determines how the policy is applied. See the guide for more. ### [](dsl-ash-policy-authorizer.html#policies-policy-authorize_if)policies.policy.authorize\_if ``` authorize_if check ``` If the check is true, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-1)Examples ``` authorize_if logged_in() ``` ``` authorize_if actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-1)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy-authorize_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-2)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy-authorize_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-policy-forbid_if)policies.policy.forbid\_if ``` forbid_if check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-2)Examples ``` forbid_if not_logged_in() ``` ``` forbid_if actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-2)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy-forbid_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-3)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy-forbid_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-1)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-policy-authorize_unless)policies.policy.authorize\_unless ``` authorize_unless check ``` If the check is false, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-3)Examples ``` authorize_unless not_logged_in() ``` ``` authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-3)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy-authorize_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-4)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy-authorize_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-2)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-policy-forbid_unless)policies.policy.forbid\_unless ``` forbid_unless check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-4)Examples ``` forbid_unless logged_in() ``` ``` forbid_unless actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-4)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy-forbid_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-5)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy-forbid_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-3)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#introspection-4)Introspection Target: [`Ash.Policy.Policy`](Ash.Policy.Policy.html) ### [](dsl-ash-policy-authorizer.html#policies-policy_group)policies.policy\_group ``` policy_group condition ``` Groups a set of policies together by some condition. If the condition on the policy group does not apply, then none of the policies within it apply. This is primarily syntactic sugar. At compile time, the conditions from the policy group are added to each policy it contains, and the list is flattened out. This exists primarily to make it easier to reason about and write policies. The following are equivalent: ``` policy_group condition1 do policy condition2 do ... end policy condition3 do ... end end ``` and ``` policy [condition1, condition2] do ... end policy [condition1, condition3] do ... end ``` ### [](dsl-ash-policy-authorizer.html#nested-dsls-2)Nested DSLs - [policy](dsl-ash-policy-authorizer.html#policies-policy_group-policy) - authorize\_if - forbid\_if - authorize\_unless - forbid\_unless ### [](dsl-ash-policy-authorizer.html#arguments-5)Arguments NameTypeDefaultDocs[`condition`](dsl-ash-policy-authorizer.html#policies-policy_group-condition)`any`A check or list of checks that must be true in order for this policy to apply. ### [](dsl-ash-policy-authorizer.html#policies-policy_group-policy)policies.policy\_group.policy ``` policy condition \\ nil ``` A policy has a name, a condition, and a list of checks. Checks apply logically in the order they are specified, from top to bottom. If no check explicitly authorizes the request, then the request is forbidden. This means that, if you want to "blacklist" instead of "whitelist", you likely want to add an `authorize_if always()` at the bottom of your policy, like so: ``` policy action_type(:read) do forbid_if not_logged_in() forbid_if user_is_denylisted() forbid_if user_is_in_denylisted_group() authorize_if always() end ``` If the policy should always run, use the `always()` check, like so: ``` policy always() do ... end ``` See the [policies guide](policies.html) for more. ### [](dsl-ash-policy-authorizer.html#nested-dsls-3)Nested DSLs - [authorize\_if](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_if) - [forbid\_if](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_if) - [authorize\_unless](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_unless) - [forbid\_unless](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_unless) ### [](dsl-ash-policy-authorizer.html#arguments-6)Arguments NameTypeDefaultDocs[`condition`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-condition)`any`A check or list of checks that must be true in order for this policy to apply. ### [](dsl-ash-policy-authorizer.html#options-6)Options NameTypeDefaultDocs[`description`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-description)`String.t`A description for the policy, used when explaining authorization results[`access_type`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-access_type)`:strict | :filter | :runtime`Determines how the policy is applied. See the guide for more. ### [](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_if)policies.policy\_group.policy.authorize\_if ``` authorize_if check ``` If the check is true, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-5)Examples ``` authorize_if logged_in() ``` ``` authorize_if actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-7)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-7)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-5)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_if)policies.policy\_group.policy.forbid\_if ``` forbid_if check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-6)Examples ``` forbid_if not_logged_in() ``` ``` forbid_if actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-8)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-8)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-6)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_unless)policies.policy\_group.policy.authorize\_unless ``` authorize_unless check ``` If the check is false, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-7)Examples ``` authorize_unless not_logged_in() ``` ``` authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-9)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-9)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-authorize_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-7)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_unless)policies.policy\_group.policy.forbid\_unless ``` forbid_unless check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-8)Examples ``` forbid_unless logged_in() ``` ``` forbid_unless actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-10)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-10)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-policy_group-policy-forbid_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-8)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#introspection-9)Introspection Target: [`Ash.Policy.Policy`](Ash.Policy.Policy.html) ### [](dsl-ash-policy-authorizer.html#introspection-10)Introspection Target: [`Ash.Policy.PolicyGroup`](Ash.Policy.PolicyGroup.html) ### [](dsl-ash-policy-authorizer.html#policies-bypass)policies.bypass ``` bypass condition \\ nil ``` A policy that, if passed, will skip all following policies. If failed, authorization moves on to the next policy ### [](dsl-ash-policy-authorizer.html#nested-dsls-4)Nested DSLs - [authorize\_if](dsl-ash-policy-authorizer.html#policies-bypass-authorize_if) - [forbid\_if](dsl-ash-policy-authorizer.html#policies-bypass-forbid_if) - [authorize\_unless](dsl-ash-policy-authorizer.html#policies-bypass-authorize_unless) - [forbid\_unless](dsl-ash-policy-authorizer.html#policies-bypass-forbid_unless) ### [](dsl-ash-policy-authorizer.html#arguments-11)Arguments NameTypeDefaultDocs[`condition`](dsl-ash-policy-authorizer.html#policies-bypass-condition)`any`A check or list of checks that must be true in order for this policy to apply. ### [](dsl-ash-policy-authorizer.html#options-11)Options NameTypeDefaultDocs[`description`](dsl-ash-policy-authorizer.html#policies-bypass-description)`String.t`A description for the policy, used when explaining authorization results[`access_type`](dsl-ash-policy-authorizer.html#policies-bypass-access_type)`:strict | :filter | :runtime`Determines how the policy is applied. See the guide for more. ### [](dsl-ash-policy-authorizer.html#policies-bypass-authorize_if)policies.bypass.authorize\_if ``` authorize_if check ``` If the check is true, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-9)Examples ``` authorize_if logged_in() ``` ``` authorize_if actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-12)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-bypass-authorize_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-12)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-bypass-authorize_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-11)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-bypass-forbid_if)policies.bypass.forbid\_if ``` forbid_if check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-10)Examples ``` forbid_if not_logged_in() ``` ``` forbid_if actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-13)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-bypass-forbid_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-13)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-bypass-forbid_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-12)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-bypass-authorize_unless)policies.bypass.authorize\_unless ``` authorize_unless check ``` If the check is false, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-11)Examples ``` authorize_unless not_logged_in() ``` ``` authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-14)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-bypass-authorize_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-14)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-bypass-authorize_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-13)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#policies-bypass-forbid_unless)policies.bypass.forbid\_unless ``` forbid_unless check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-12)Examples ``` forbid_unless logged_in() ``` ``` forbid_unless actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-15)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#policies-bypass-forbid_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-15)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#policies-bypass-forbid_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-14)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#introspection-15)Introspection Target: [`Ash.Policy.Policy`](Ash.Policy.Policy.html) ## [](dsl-ash-policy-authorizer.html#field_policies)field\_policies Authorize access to specific fields via policies scoped to fields. If *any* field policies exist then *all* fields must be authorized by a field policy. If you want a "deny-list" style, then you can add policies for specific fields and add a catch-all policy using the special field name `:*`. All policies that apply to a field must be authorized. The only exception to the above behavior is primary keys, which can always be read by everyone. Additionally, keep in mind that adding [`Ash.Policy.Authorizer`](Ash.Policy.Authorizer.html) will require that all actions pass policies. If you want to just add field policies, you will need to add a policy that allows all access explicitly, i.e ``` policies do policy always() do authorize_if always() end end ``` Using expressions: unlike in regular policies, expressions in field policies cannot refer to related entities currently. Instead, you will need to create aggregates or expression calculations that return the results you want to reference. In results, forbidden fields will be replaced with a special value: `%Ash.ForbiddenField{}`. When these fields are referred to in filters, they will be replaced with an expression that evaluates to `nil`. To support this behavior, only expression/filter checks are allowed in field policies. ### [](dsl-ash-policy-authorizer.html#nested-dsls-5)Nested DSLs - [field\_policy\_bypass](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass) - authorize\_if - forbid\_if - authorize\_unless - forbid\_unless - [field\_policy](dsl-ash-policy-authorizer.html#field_policies-field_policy) - authorize\_if - forbid\_if - authorize\_unless - forbid\_unless ### [](dsl-ash-policy-authorizer.html#examples-13)Examples ``` field_policies do field_policy :admin_only_field do authorize_if actor_attribute_equals(:admin, true) end end ``` ``` # Example of denylist style field_policies do field_policy [:sensitive, :fields] do authorize_if actor_attribute_equals(:admin, true) end field_policy :* do authorize_if always() end end ``` ### [](dsl-ash-policy-authorizer.html#options-16)Options NameTypeDefaultDocs[`private_fields`](dsl-ash-policy-authorizer.html#field_policies-private_fields)`:show | :hide | :include``:show`How private fields should be handeled by field policies in internal functions. See the [Policies guide](policies.html#field-policies) for more. ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass)field\_policies.field\_policy\_bypass ``` field_policy_bypass fields, condition \\ nil ``` A field policy that, if passed, will skip all following field policies for that field or fields. If failed, field authorization moves on to the next policy ### [](dsl-ash-policy-authorizer.html#nested-dsls-6)Nested DSLs - [authorize\_if](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_if) - [forbid\_if](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_if) - [authorize\_unless](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_unless) - [forbid\_unless](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_unless) ### [](dsl-ash-policy-authorizer.html#arguments-16)Arguments NameTypeDefaultDocs[`fields`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-fields)`atom | list(atom)`The field or fields that the policy applies to.[`condition`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-condition)`any`A check or list of checks that must be true in order for this field policy to apply. If not specified, it always applies. ### [](dsl-ash-policy-authorizer.html#options-17)Options NameTypeDefaultDocs[`description`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-description)`String.t`A description for the policy, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_if)field\_policies.field\_policy\_bypass.authorize\_if ``` authorize_if check ``` If the check is true, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-14)Examples ``` authorize_if logged_in() ``` ``` authorize_if actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-17)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-18)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-16)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_if)field\_policies.field\_policy\_bypass.forbid\_if ``` forbid_if check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-15)Examples ``` forbid_if not_logged_in() ``` ``` forbid_if actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-18)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-19)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-17)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_unless)field\_policies.field\_policy\_bypass.authorize\_unless ``` authorize_unless check ``` If the check is false, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-16)Examples ``` authorize_unless not_logged_in() ``` ``` authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-19)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-20)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-authorize_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-18)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_unless)field\_policies.field\_policy\_bypass.forbid\_unless ``` forbid_unless check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-17)Examples ``` forbid_unless logged_in() ``` ``` forbid_unless actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-20)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-21)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy_bypass-forbid_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-19)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#introspection-20)Introspection Target: [`Ash.Policy.FieldPolicy`](Ash.Policy.FieldPolicy.html) ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy)field\_policies.field\_policy ``` field_policy fields, condition \\ nil ``` Field policies behave similarly to policies. See `Ash.Policy.Authorizer.field_policies` for more. ### [](dsl-ash-policy-authorizer.html#nested-dsls-7)Nested DSLs - [authorize\_if](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_if) - [forbid\_if](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_if) - [authorize\_unless](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_unless) - [forbid\_unless](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_unless) ### [](dsl-ash-policy-authorizer.html#arguments-21)Arguments NameTypeDefaultDocs[`fields`](dsl-ash-policy-authorizer.html#field_policies-field_policy-fields)`atom | list(atom)`The field or fields that the policy applies to.[`condition`](dsl-ash-policy-authorizer.html#field_policies-field_policy-condition)`any`A check or list of checks that must be true in order for this field policy to apply. If not specified, it always applies. ### [](dsl-ash-policy-authorizer.html#options-22)Options NameTypeDefaultDocs[`description`](dsl-ash-policy-authorizer.html#field_policies-field_policy-description)`String.t`A description for the policy, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_if)field\_policies.field\_policy.authorize\_if ``` authorize_if check ``` If the check is true, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-18)Examples ``` authorize_if logged_in() ``` ``` authorize_if actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-22)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-23)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-21)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_if)field\_policies.field\_policy.forbid\_if ``` forbid_if check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-19)Examples ``` forbid_if not_logged_in() ``` ``` forbid_if actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-23)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_if-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-24)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_if-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-22)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_unless)field\_policies.field\_policy.authorize\_unless ``` authorize_unless check ``` If the check is false, the request is authorized, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-20)Examples ``` authorize_unless not_logged_in() ``` ``` authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups) ``` ### [](dsl-ash-policy-authorizer.html#arguments-24)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-25)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy-authorize_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-23)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_unless)field\_policies.field\_policy.forbid\_unless ``` forbid_unless check ``` If the check is true, the request is forbidden, otherwise run remaining checks. ### [](dsl-ash-policy-authorizer.html#examples-21)Examples ``` forbid_unless logged_in() ``` ``` forbid_unless actor_attribute_matches_record(:group, :group) ``` ### [](dsl-ash-policy-authorizer.html#arguments-25)Arguments NameTypeDefaultDocs[`check`](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_unless-check)`any | module`The check to run. See [`Ash.Policy.Check`](Ash.Policy.Check.html) for more. ### [](dsl-ash-policy-authorizer.html#options-26)Options NameTypeDefaultDocs[`name`](dsl-ash-policy-authorizer.html#field_policies-field_policy-forbid_unless-name)`String.t`A short name or description for the check, used when explaining authorization results ### [](dsl-ash-policy-authorizer.html#introspection-24)Introspection Target: [`Ash.Policy.Check`](Ash.Policy.Check.html) ### [](dsl-ash-policy-authorizer.html#introspection-25)Introspection Target: [`Ash.Policy.FieldPolicy`](Ash.Policy.FieldPolicy.html) [← Previous Page Ash.Notifier.PubSub](dsl-ash-notifier-pubsub.html) [Next Page → Ash.DataLayer.Ets](dsl-ash-datalayer-ets.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/dsls/DSL-Ash.Policy.Authorizer.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Reactor [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/dsls/DSL-Ash.Reactor.md#L1 "View Source") [`Ash.Reactor`](Ash.Reactor.html) is a [`Reactor`](https://hex.pm/packages/reactor) extension which provides steps for working with Ash resources and actions. See the [Ash Reactor Guide](reactor.html) for more information. ## [](dsl-ash-reactor.html#ash)ash Ash-related configuration for the [`Ash.Reactor`](Ash.Reactor.html) extension ### [](dsl-ash-reactor.html#options)Options NameTypeDefaultDocs[`default_domain`](dsl-ash-reactor.html#ash-default_domain)`module`A domain to use by default when calling actions ### [](dsl-ash-reactor.html#reactor-action)reactor.action ``` action name, resource, action \\ nil ``` Declares a step that will call a generic action on a resource. #### Undo behaviour This step has three different modes of undo. - `never` - The result of the action is never undone. This is the default. - `always` - The `undo_action` will always be called. - `outside_transaction` - The `undo_action` will not be called when running inside a `transaction` block, but will be otherwise. ### [](dsl-ash-reactor.html#nested-dsls)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-action-actor) - [context](dsl-ash-reactor.html#reactor-action-context) - [inputs](dsl-ash-reactor.html#reactor-action-inputs) - [tenant](dsl-ash-reactor.html#reactor-action-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-action-wait_for) ### [](dsl-ash-reactor.html#arguments)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-action-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-action-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-action-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-1)Options NameTypeDefaultDocs[`domain`](dsl-ash-reactor.html#reactor-action-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-action-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-action-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-action-description)`String.t`A description for the step[`undo_action`](dsl-ash-reactor.html#reactor-action-undo_action)`atom`The name of the action to call on the resource when the step is to be undone.[`undo`](dsl-ash-reactor.html#reactor-action-undo)`:always | :never | :outside_transaction``:never`How to handle undoing this action ### [](dsl-ash-reactor.html#reactor-action-actor)reactor.action.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-1)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-action-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-2)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-action-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-action-context)reactor.action.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-2)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-action-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-3)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-action-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-1)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-action-inputs)reactor.action.inputs ``` inputs template ``` Specify the inputs for an action ### [](dsl-ash-reactor.html#examples)Examples ``` inputs %{ author: result(:get_user), title: input(:title), body: input(:body) } ``` ``` inputs(author: result(:get_user)) ``` ### [](dsl-ash-reactor.html#arguments-3)Arguments NameTypeDefaultDocs[`template`](dsl-ash-reactor.html#reactor-action-inputs-template)`%{optional(atom) => Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value} | keyword(Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value)` ### [](dsl-ash-reactor.html#options-4)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-action-inputs-transform)`(any -> any) | module | nil`An optional transformation function which will transform the inputs before executing the action. ### [](dsl-ash-reactor.html#introspection-2)Introspection Target: [`Ash.Reactor.Dsl.Inputs`](Ash.Reactor.Dsl.Inputs.html) ### [](dsl-ash-reactor.html#reactor-action-tenant)reactor.action.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-4)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-action-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-5)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-action-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-3)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-action-wait_for)reactor.action.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-1)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-5)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-action-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-6)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-action-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-4)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-5)Introspection Target: [`Ash.Reactor.Dsl.Action`](Ash.Reactor.Dsl.Action.html) ### [](dsl-ash-reactor.html#reactor-ash_step)reactor.ash\_step ``` ash_step name, impl \\ nil ``` Specifies a Ash.Reactor step. This is basically a wrapper around `Reactor.step`, in order to handle any returned notifications from the run step/function. See the [`Reactor.Step`](../reactor/0.10.3/Reactor.Step.html) behaviour for more information. ### [](dsl-ash-reactor.html#nested-dsls-1)Nested DSLs - [argument](dsl-ash-reactor.html#reactor-ash_step-argument) - [wait\_for](dsl-ash-reactor.html#reactor-ash_step-wait_for) ### [](dsl-ash-reactor.html#examples-2)Examples ``` ash_step :create_post, MyApp.CreatePostStep do argument :title, input(:title) end ``` ``` ash_step :create_post do argument :title, input(:title) run fn %{title: title}, _ -> MyApp.Post.create(title, return_notifications?: true) end end ``` ### [](dsl-ash-reactor.html#arguments-6)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-ash_step-name)`atom`A unique name for the step. Used when choosing the return value of the Reactor and for arguments into other steps.[`impl`](dsl-ash-reactor.html#reactor-ash_step-impl)`module | nil`A module that implements the [`Reactor.Step`](../reactor/0.10.3/Reactor.Step.html) behaviour that provides the implementation. ### [](dsl-ash-reactor.html#options-7)Options NameTypeDefaultDocs[`run`](dsl-ash-reactor.html#reactor-ash_step-run)`(any -> any) | mfa | (any, any -> any) | mfa`Provide an anonymous function which implements the `run/3` callback. Cannot be provided at the same time as the `impl` argument.[`undo`](dsl-ash-reactor.html#reactor-ash_step-undo)`(any -> any) | mfa | (any, any -> any) | mfa | (any, any, any -> any) | mfa`Provide an anonymous function which implements the `undo/4` callback. Cannot be provided at the same time as the `impl` argument.[`compensate`](dsl-ash-reactor.html#reactor-ash_step-compensate)`(any -> any) | mfa | (any, any -> any) | mfa | (any, any, any -> any) | mfa`Provide an anonymous function which implements the `undo/4` callback. Cannot be provided at the same time as the `impl` argument.[`max_retries`](dsl-ash-reactor.html#reactor-ash_step-max_retries)`:infinity | non_neg_integer``:infinity`The maximum number of times that the step can be retried before failing. Only used when the result of the `compensate/4` callback is `:retry`.[`async?`](dsl-ash-reactor.html#reactor-ash_step-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`transform`](dsl-ash-reactor.html#reactor-ash_step-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the entire argument map before it is passed to the step. ### [](dsl-ash-reactor.html#reactor-ash_step-argument)reactor.ash\_step.argument ``` argument name, source \\ nil ``` Specifies an argument to a Reactor step. Each argument is a value which is either the result of another step, or an input value. Individual arguments can be transformed with an arbitrary function before being passed to any steps. ### [](dsl-ash-reactor.html#examples-3)Examples ``` argument :name, input(:name) ``` ``` argument :year, input(:date, [:year]) ``` ``` argument :user, result(:create_user) ``` ``` argument :user_id, result(:create_user) do transform & &1.id end ``` ``` argument :user_id, result(:create_user, [:id]) ``` ``` argument :three, value(3) ``` ### [](dsl-ash-reactor.html#arguments-7)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-ash_step-argument-name)`atom`The name of the argument which will be used as the key in the `arguments` map passed to the implementation.[`source`](dsl-ash-reactor.html#reactor-ash_step-argument-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the argument. See [`Reactor.Dsl.Argument`](../reactor/0.10.3/Reactor.Dsl.Argument.html) for more information. ### [](dsl-ash-reactor.html#options-8)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-ash_step-argument-description)`String.t`An optional description for the argument.[`transform`](dsl-ash-reactor.html#reactor-ash_step-argument-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the argument before it is passed to the step. ### [](dsl-ash-reactor.html#introspection-6)Introspection Target: [`Reactor.Dsl.Argument`](../reactor/0.10.3/Reactor.Dsl.Argument.html) ### [](dsl-ash-reactor.html#reactor-ash_step-wait_for)reactor.ash\_step.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-4)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-8)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-ash_step-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-9)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-ash_step-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-7)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-8)Introspection Target: [`Ash.Reactor.Dsl.AshStep`](Ash.Reactor.Dsl.AshStep.html) ### [](dsl-ash-reactor.html#reactor-bulk_create)reactor.bulk\_create ``` bulk_create name, resource, action \\ nil ``` Declares a step which will call a create action on a resource with a collection of inputs. ### [](dsl-ash-reactor.html#check-the-docs)Check the docs! Make sure to thoroughly read and understand the documentation in [`Ash.bulk_create/4`](Ash.html#bulk_create/4) before using. Read each option and note the default values. By default, bulk creates don't return records or errors, and don't emit notifications. Caveats/differences from [`Ash.bulk_create/4`](Ash.html#bulk_create/4): 1. `max_concurrency` specifies the number of tasks that Ash will start to process batches, and has no effect on Reactor concurrency targets. It's could be possible to create a very large number of processes if a number of steps are running bulk actions with a high degree of concurrency. 2. Setting `notify?` to `true` will cause both `notify?` and `return_notifications?` to be set to true in the underlying call to [`Ash.bulk_create/4`](Ash.html#bulk_create/4). Notifications will then be managed by the [`Ash.Reactor.Notifications`](Ash.Reactor.Notifications.html) Reactor middleware. 3. If you specify an undo action it must be a generic action which takes the bulk result as it's only argument. #### Undo behaviour This step has three different modes of undo. - `never` - The result of the action is never undone. This is the default. - `always` - The `undo_action` will always be called. - `outside_transaction` - The `undo_action` will not be called when running inside a `transaction` block, but will be otherwise. ### [](dsl-ash-reactor.html#nested-dsls-2)Nested DSLs - [context](dsl-ash-reactor.html#reactor-bulk_create-context) - [actor](dsl-ash-reactor.html#reactor-bulk_create-actor) - [load](dsl-ash-reactor.html#reactor-bulk_create-load) - [tenant](dsl-ash-reactor.html#reactor-bulk_create-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-bulk_create-wait_for) ### [](dsl-ash-reactor.html#examples-5)Examples ``` bulk_create :create_posts, MyApp.Post, :create do initial input(:titles) actor result(:get_user) tenant result(:get_organisation, [:id]) end ``` ### [](dsl-ash-reactor.html#arguments-9)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-bulk_create-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-bulk_create-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-bulk_create-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-10)Options NameTypeDefaultDocs[`initial`](dsl-ash-reactor.html#reactor-bulk_create-initial)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`A collection of inputs to pass to the create action. Must implement the [`Enumerable`](../elixir/Enumerable.html) protocol.[`assume_casted?`](dsl-ash-reactor.html#reactor-bulk_create-assume_casted?)`boolean``false`Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting[`authorize_changeset_with`](dsl-ash-reactor.html#reactor-bulk_create-authorize_changeset_with)`:filter | :error``:filter`If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error[`authorize_query_with`](dsl-ash-reactor.html#reactor-bulk_create-authorize_query_with)`:filter | :error``:filter`If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error[`batch_size`](dsl-ash-reactor.html#reactor-bulk_create-batch_size)`nil | pos_integer`The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100.[`max_concurrency`](dsl-ash-reactor.html#reactor-bulk_create-max_concurrency)`non_neg_integer``0`If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously.[`notification_metadata`](dsl-ash-reactor.html#reactor-bulk_create-notification_metadata)`map | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value``%{}`Metadata to be merged into the metadata field for all notifications sent from this operation.[`notify?`](dsl-ash-reactor.html#reactor-bulk_create-notify?)`boolean``false`Whether or not to generate any notifications. This may be intensive for large bulk actions.[`read_action`](dsl-ash-reactor.html#reactor-bulk_create-read_action)`atom`The action to use when building the read query.[`return_errors?`](dsl-ash-reactor.html#reactor-bulk_create-return_errors?)`boolean``false`Whether or not to return all of the errors that occur. Defaults to false to account for large inserts.[`return_records?`](dsl-ash-reactor.html#reactor-bulk_create-return_records?)`boolean``false`Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts.[`return_stream?`](dsl-ash-reactor.html#reactor-bulk_create-return_stream?)`boolean``false`If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned.[`rollback_on_error?`](dsl-ash-reactor.html#reactor-bulk_create-rollback_on_error?)`boolean``true`Whether or not to rollback the transaction on error, if the resource is in a transaction.[`select`](dsl-ash-reactor.html#reactor-bulk_create-select)`atom | list(atom)`A select statement to apply to records. Ignored if `return_records?` is not `true`.[`skip_unknown_inputs`](dsl-ash-reactor.html#reactor-bulk_create-skip_unknown_inputs)`atom | String.t | list(atom | String.t)`A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys.[`sorted?`](dsl-ash-reactor.html#reactor-bulk_create-sorted?)`boolean``false`Whether or not to sort results by their input position, in cases where `return_records?` is set to `true`.[`stop_on_error?`](dsl-ash-reactor.html#reactor-bulk_create-stop_on_error?)`boolean``false`If `true`, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped.[`success_state`](dsl-ash-reactor.html#reactor-bulk_create-success_state)`:success | :partial_success``:success`Bulk results can be entirely or partially successful. Chooses the [`Ash.BulkResult`](Ash.BulkResult.html) state to consider the step a success.[`timeout`](dsl-ash-reactor.html#reactor-bulk_create-timeout)`timeout`If none is provided, the timeout configured on the domain is used (which defaults to `30_000`).[`transaction`](dsl-ash-reactor.html#reactor-bulk_create-transaction)`:all | :batch | false``:batch`Whether or not to wrap the entire execution in a transaction, each batch, or not at all.[`upsert_fields`](dsl-ash-reactor.html#reactor-bulk_create-upsert_fields)`atom | list(atom)`The fields to upsert. If not set, the action's `upsert_fields` is used.[`upsert_identity`](dsl-ash-reactor.html#reactor-bulk_create-upsert_identity)`atom`The identity to use for the upsert[`upsert?`](dsl-ash-reactor.html#reactor-bulk_create-upsert?)`boolean``false`Whether or not this action should be executed as an upsert.[`domain`](dsl-ash-reactor.html#reactor-bulk_create-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-bulk_create-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-bulk_create-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-bulk_create-description)`String.t`A description for the step[`undo_action`](dsl-ash-reactor.html#reactor-bulk_create-undo_action)`atom`The name of the action to call on the resource when the step is to be undone.[`undo`](dsl-ash-reactor.html#reactor-bulk_create-undo)`:always | :never | :outside_transaction``:never`How to handle undoing this action ### [](dsl-ash-reactor.html#reactor-bulk_create-context)reactor.bulk\_create.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-10)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-bulk_create-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-11)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_create-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-9)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-bulk_create-actor)reactor.bulk\_create.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-11)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-bulk_create-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-12)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_create-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-10)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-bulk_create-load)reactor.bulk\_create.load ``` load source ``` Allows the addition of an Ash load statement to the action ### [](dsl-ash-reactor.html#arguments-12)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-bulk_create-load-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the load ### [](dsl-ash-reactor.html#options-13)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_create-load-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the load before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-11)Introspection Target: [`Ash.Reactor.Dsl.ActionLoad`](Ash.Reactor.Dsl.ActionLoad.html) ### [](dsl-ash-reactor.html#reactor-bulk_create-tenant)reactor.bulk\_create.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-13)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-bulk_create-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-14)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_create-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-12)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-bulk_create-wait_for)reactor.bulk\_create.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-6)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-14)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-bulk_create-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-15)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-bulk_create-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-13)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-14)Introspection Target: [`Ash.Reactor.Dsl.BulkCreate`](Ash.Reactor.Dsl.BulkCreate.html) ### [](dsl-ash-reactor.html#reactor-bulk_update)reactor.bulk\_update ``` bulk_update name, resource, action \\ nil ``` Declares a step which will call an update action on a resource with a collection of inputs. ### [](dsl-ash-reactor.html#check-the-docs-1)Check the docs! Make sure to thoroughly read and understand the documentation in [`Ash.bulk_update/4`](Ash.html#bulk_update/4) before using. Read each option and note the default values. By default, bulk updates don't return records or errors, and don't emit notifications. Caveats/differences from [`Ash.bulk_update/4`](Ash.html#bulk_update/4): 1. `max_concurrency` specifies the number of tasks that Ash will start to process batches, and has no effect on Reactor concurrency targets. It's could be possible to create a very large number of processes if a number of steps are running bulk actions with a high degree of concurrency. 2. Setting `notify?` to `true` will cause both `notify?` and `return_notifications?` to be set to true in the underlying call to [`Ash.bulk_create/4`](Ash.html#bulk_create/4). Notifications will then be managed by the [`Ash.Reactor.Notifications`](Ash.Reactor.Notifications.html) Reactor middleware. 3. If you specify an undo action it must be a generic action which takes the bulk result as it's only argument. #### Undo behaviour This step has three different modes of undo. - `never` - The result of the action is never undone. This is the default. - `always` - The `undo_action` will always be called. - `outside_transaction` - The `undo_action` will not be called when running inside a `transaction` block, but will be otherwise. ### [](dsl-ash-reactor.html#nested-dsls-3)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-bulk_update-actor) - [context](dsl-ash-reactor.html#reactor-bulk_update-context) - [inputs](dsl-ash-reactor.html#reactor-bulk_update-inputs) - [tenant](dsl-ash-reactor.html#reactor-bulk_update-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-bulk_update-wait_for) ### [](dsl-ash-reactor.html#examples-7)Examples ``` bulk_update :publish_posts, MyApp.Post, :publish do initial input(:posts), actor result(:get_user) end ``` ### [](dsl-ash-reactor.html#arguments-15)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-bulk_update-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-bulk_update-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-bulk_update-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-16)Options NameTypeDefaultDocs[`initial`](dsl-ash-reactor.html#reactor-bulk_update-initial)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`A collection of inputs to pass to the create action. Must implement the [`Enumerable`](../elixir/Enumerable.html) protocol.[`allow_stream_with`](dsl-ash-reactor.html#reactor-bulk_update-allow_stream_with)`:keyset | :offset | :full_read``:keyset`The 'worst' strategy allowed to be used to fetch records if the :stream strategy is chosen. See the [`Ash.stream!/2`](Ash.html#stream!/2) docs for more.[`assume_casted?`](dsl-ash-reactor.html#reactor-bulk_update-assume_casted?)`boolean``false`Whether or not to cast attributes and arguments as input. This is an optimization for cases where the input is already casted and/or not in need of casting[`atomic_update`](dsl-ash-reactor.html#reactor-bulk_update-atomic_update)`map`A map of atomic updates to apply. See [`Ash.Changeset.atomic_update/3`](Ash.Changeset.html#atomic_update/3) for more.[`authorize_changeset_with`](dsl-ash-reactor.html#reactor-bulk_update-authorize_changeset_with)`:filter | :error``:filter`If set to `:error`, instead of filtering unauthorized changes, unauthorized changes will raise an appropriate forbidden error[`authorize_query_with`](dsl-ash-reactor.html#reactor-bulk_update-authorize_query_with)`:filter | :error``:filter`If set to `:error`, instead of filtering unauthorized query results, unauthorized query results will raise an appropriate forbidden error[`authorize_query?`](dsl-ash-reactor.html#reactor-bulk_update-authorize_query?)`boolean``true`If a query is given, determines whether or not authorization is run on that query.[`batch_size`](dsl-ash-reactor.html#reactor-bulk_update-batch_size)`nil | pos_integer`The number of records to include in each batch. Defaults to the `default_limit` or `max_page_size` of the action, or 100.[`filter`](dsl-ash-reactor.html#reactor-bulk_update-filter)`map | keyword`A filter to apply to records. This is also applied to a stream of inputs.[`lock`](dsl-ash-reactor.html#reactor-bulk_update-lock)`any`A lock statement to add onto the query.[`max_concurrency`](dsl-ash-reactor.html#reactor-bulk_update-max_concurrency)`non_neg_integer``0`If set to a value greater than 0, up to that many tasks will be started to run batches asynchronously.[`notification_metadata`](dsl-ash-reactor.html#reactor-bulk_update-notification_metadata)`map | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value``%{}`Metadata to be merged into the metadata field for all notifications sent from this operation.[`notify?`](dsl-ash-reactor.html#reactor-bulk_update-notify?)`boolean``false`Whether or not to generate any notifications. This may be intensive for large bulk actions.[`page`](dsl-ash-reactor.html#reactor-bulk_update-page)`keyword``[]`Pagination options, see [`Ash.read/2`](Ash.html#read/2) for more.[`read_action`](dsl-ash-reactor.html#reactor-bulk_update-read_action)`atom`The action to use when building the read query.[`return_errors?`](dsl-ash-reactor.html#reactor-bulk_update-return_errors?)`boolean``false`Whether or not to return all of the errors that occur. Defaults to false to account for large inserts.[`return_records?`](dsl-ash-reactor.html#reactor-bulk_update-return_records?)`boolean``false`Whether or not to return all of the records that were inserted. Defaults to false to account for large inserts.[`return_stream?`](dsl-ash-reactor.html#reactor-bulk_update-return_stream?)`boolean``false`If set to `true`, instead of an [`Ash.BulkResult`](Ash.BulkResult.html), a mixed stream is returned.[`reuse_values?`](dsl-ash-reactor.html#reactor-bulk_update-reuse_values?)`boolean``false`Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer.[`rollback_on_error?`](dsl-ash-reactor.html#reactor-bulk_update-rollback_on_error?)`boolean``true`Whether or not to rollback the transaction on error, if the resource is in a transaction.[`select`](dsl-ash-reactor.html#reactor-bulk_update-select)`atom | list(atom)`A select statement to apply to records. Ignored if `return_records?` is not `true`.[`skip_unknown_inputs`](dsl-ash-reactor.html#reactor-bulk_update-skip_unknown_inputs)`atom | String.t | list(atom | String.t)`A list of inputs that, if provided, will be ignored if they are not recognized by the action. Use `:*` to indicate all unknown keys.[`sorted?`](dsl-ash-reactor.html#reactor-bulk_update-sorted?)`boolean``false`Whether or not to sort results by their input position, in cases where `return_records?` is set to `true`.[`stop_on_error?`](dsl-ash-reactor.html#reactor-bulk_update-stop_on_error?)`boolean``false`If `true`, the first encountered error will stop the action and be returned. Otherwise, errors will be skipped.[`strategy`](dsl-ash-reactor.html#reactor-bulk_update-strategy)`list(:atomic | :atomic_batches | :stream)``[:atomic]`The strategy or strategies to enable. `:stream` is used in all cases if the data layer does not support atomics.[`stream_batch_size`](dsl-ash-reactor.html#reactor-bulk_update-stream_batch_size)`pos_integer`Batch size to use if provided a query and the query must be streamed.[`stream_with`](dsl-ash-reactor.html#reactor-bulk_update-stream_with)`:keyset | :offset | :full_read`The specific strategy to use to fetch records. See [`Ash.stream!/2`](Ash.html#stream!/2) docs for more.[`success_state`](dsl-ash-reactor.html#reactor-bulk_update-success_state)`:success | :partial_success``:success`Bulk results can be entirely or partially successful. Chooses the [`Ash.BulkResult`](Ash.BulkResult.html) state to consider the step a success.[`timeout`](dsl-ash-reactor.html#reactor-bulk_update-timeout)`timeout`If none is provided, the timeout configured on the domain is used (which defaults to `30_000`).[`transaction`](dsl-ash-reactor.html#reactor-bulk_update-transaction)`:all | :batch | false``:batch`Whether or not to wrap the entire execution in a transaction, each batch, or not at all.[`domain`](dsl-ash-reactor.html#reactor-bulk_update-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-bulk_update-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-bulk_update-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-bulk_update-description)`String.t`A description for the step[`undo_action`](dsl-ash-reactor.html#reactor-bulk_update-undo_action)`atom`The name of the action to call on the resource when the step is to be undone.[`undo`](dsl-ash-reactor.html#reactor-bulk_update-undo)`:always | :never | :outside_transaction``:never`How to handle undoing this action ### [](dsl-ash-reactor.html#reactor-bulk_update-actor)reactor.bulk\_update.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-16)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-bulk_update-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-17)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_update-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-15)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-bulk_update-context)reactor.bulk\_update.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-17)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-bulk_update-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-18)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_update-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-16)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-bulk_update-inputs)reactor.bulk\_update.inputs ``` inputs template ``` Specify the inputs for an action ### [](dsl-ash-reactor.html#examples-8)Examples ``` inputs %{ author: result(:get_user), title: input(:title), body: input(:body) } ``` ``` inputs(author: result(:get_user)) ``` ### [](dsl-ash-reactor.html#arguments-18)Arguments NameTypeDefaultDocs[`template`](dsl-ash-reactor.html#reactor-bulk_update-inputs-template)`%{optional(atom) => Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value} | keyword(Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value)` ### [](dsl-ash-reactor.html#options-19)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_update-inputs-transform)`(any -> any) | module | nil`An optional transformation function which will transform the inputs before executing the action. ### [](dsl-ash-reactor.html#introspection-17)Introspection Target: [`Ash.Reactor.Dsl.Inputs`](Ash.Reactor.Dsl.Inputs.html) ### [](dsl-ash-reactor.html#reactor-bulk_update-tenant)reactor.bulk\_update.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-19)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-bulk_update-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-20)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-bulk_update-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-18)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-bulk_update-wait_for)reactor.bulk\_update.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-9)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-20)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-bulk_update-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-21)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-bulk_update-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-19)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-20)Introspection Target: [`Ash.Reactor.Dsl.BulkUpdate`](Ash.Reactor.Dsl.BulkUpdate.html) ### [](dsl-ash-reactor.html#reactor-change)reactor.change ``` change name, change ``` Declares a step that will modify a changeset. ### [](dsl-ash-reactor.html#nested-dsls-4)Nested DSLs - [argument](dsl-ash-reactor.html#reactor-change-argument) - [wait\_for](dsl-ash-reactor.html#reactor-change-wait_for) ### [](dsl-ash-reactor.html#arguments-21)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-change-name)`atom`A unique name for this step.[`change`](dsl-ash-reactor.html#reactor-change-change)`(any, any -> any) | module`The module and options for a change. Also accepts a function that takes the changeset and the context. See [`Ash.Resource.Change.Builtins`](Ash.Resource.Change.Builtins.html) for builtin changes. ### [](dsl-ash-reactor.html#options-22)Options NameTypeDefaultDocs[`initial`](dsl-ash-reactor.html#reactor-change-initial)`module | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`The initial value to work from, either a resource or a changeset[`description`](dsl-ash-reactor.html#reactor-change-description)`String.t | nil`An optional description for the change[`only_when_valid?`](dsl-ash-reactor.html#reactor-change-only_when_valid?)`boolean``false`If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here.[`where`](dsl-ash-reactor.html#reactor-change-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this change to apply. These validations failing will result in this change being ignored.[`fail_if_invalid?`](dsl-ash-reactor.html#reactor-change-fail_if_invalid?)`boolean``false`Fail if the result of the change is an invalid changeset ### [](dsl-ash-reactor.html#reactor-change-argument)reactor.change.argument ``` argument name, source \\ nil ``` Specifies an argument to a Reactor step. Each argument is a value which is either the result of another step, or an input value. Individual arguments can be transformed with an arbitrary function before being passed to any steps. ### [](dsl-ash-reactor.html#examples-10)Examples ``` argument :name, input(:name) ``` ``` argument :year, input(:date, [:year]) ``` ``` argument :user, result(:create_user) ``` ``` argument :user_id, result(:create_user) do transform & &1.id end ``` ``` argument :user_id, result(:create_user, [:id]) ``` ``` argument :three, value(3) ``` ### [](dsl-ash-reactor.html#arguments-22)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-change-argument-name)`atom`The name of the argument which will be used as the key in the `arguments` map passed to the implementation.[`source`](dsl-ash-reactor.html#reactor-change-argument-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the argument. See [`Reactor.Dsl.Argument`](../reactor/0.10.3/Reactor.Dsl.Argument.html) for more information. ### [](dsl-ash-reactor.html#options-23)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-change-argument-description)`String.t`An optional description for the argument.[`transform`](dsl-ash-reactor.html#reactor-change-argument-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the argument before it is passed to the step. ### [](dsl-ash-reactor.html#introspection-21)Introspection Target: [`Reactor.Dsl.Argument`](../reactor/0.10.3/Reactor.Dsl.Argument.html) ### [](dsl-ash-reactor.html#reactor-change-wait_for)reactor.change.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-11)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-23)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-change-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-24)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-change-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-22)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-23)Introspection Target: [`Ash.Reactor.Dsl.Change`](Ash.Reactor.Dsl.Change.html) ### [](dsl-ash-reactor.html#reactor-create)reactor.create ``` create name, resource, action \\ nil ``` Declares a step that will call a create action on a resource. #### Undo behaviour This step has three different modes of undo. - `never` - The result of the action is never undone. This is the default. - `always` - The `undo_action` will always be called. - `outside_transaction` - The `undo_action` will not be called when running inside a `transaction` block, but will be otherwise. ### [](dsl-ash-reactor.html#nested-dsls-5)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-create-actor) - [context](dsl-ash-reactor.html#reactor-create-context) - [inputs](dsl-ash-reactor.html#reactor-create-inputs) - [load](dsl-ash-reactor.html#reactor-create-load) - [tenant](dsl-ash-reactor.html#reactor-create-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-create-wait_for) ### [](dsl-ash-reactor.html#examples-12)Examples ``` create :create_post, MyApp.Post, :create do inputs %{ title: input(:post_title), author_id: result(:get_user, [:id]) } actor result(:get_user) tenant result(:get_organisation, [:id]) end ``` ### [](dsl-ash-reactor.html#arguments-24)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-create-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-create-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-create-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-25)Options NameTypeDefaultDocs[`initial`](dsl-ash-reactor.html#reactor-create-initial)`nil | module | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`The initial value passed into the action.[`upsert_identity`](dsl-ash-reactor.html#reactor-create-upsert_identity)`atom`The identity to use for the upsert[`upsert?`](dsl-ash-reactor.html#reactor-create-upsert?)`boolean``false`Whether or not this action should be executed as an upsert.[`domain`](dsl-ash-reactor.html#reactor-create-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-create-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-create-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-create-description)`String.t`A description for the step[`undo_action`](dsl-ash-reactor.html#reactor-create-undo_action)`atom`The name of the action to call on the resource when the step is to be undone.[`undo`](dsl-ash-reactor.html#reactor-create-undo)`:always | :never | :outside_transaction``:never`How to handle undoing this action ### [](dsl-ash-reactor.html#reactor-create-actor)reactor.create.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-25)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-create-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-26)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-create-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-24)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-create-context)reactor.create.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-26)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-create-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-27)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-create-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-25)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-create-inputs)reactor.create.inputs ``` inputs template ``` Specify the inputs for an action ### [](dsl-ash-reactor.html#examples-13)Examples ``` inputs %{ author: result(:get_user), title: input(:title), body: input(:body) } ``` ``` inputs(author: result(:get_user)) ``` ### [](dsl-ash-reactor.html#arguments-27)Arguments NameTypeDefaultDocs[`template`](dsl-ash-reactor.html#reactor-create-inputs-template)`%{optional(atom) => Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value} | keyword(Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value)` ### [](dsl-ash-reactor.html#options-28)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-create-inputs-transform)`(any -> any) | module | nil`An optional transformation function which will transform the inputs before executing the action. ### [](dsl-ash-reactor.html#introspection-26)Introspection Target: [`Ash.Reactor.Dsl.Inputs`](Ash.Reactor.Dsl.Inputs.html) ### [](dsl-ash-reactor.html#reactor-create-load)reactor.create.load ``` load source ``` Allows the addition of an Ash load statement to the action ### [](dsl-ash-reactor.html#arguments-28)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-create-load-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the load ### [](dsl-ash-reactor.html#options-29)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-create-load-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the load before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-27)Introspection Target: [`Ash.Reactor.Dsl.ActionLoad`](Ash.Reactor.Dsl.ActionLoad.html) ### [](dsl-ash-reactor.html#reactor-create-tenant)reactor.create.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-29)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-create-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-30)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-create-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-28)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-create-wait_for)reactor.create.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-14)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-30)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-create-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-31)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-create-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-29)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-30)Introspection Target: [`Ash.Reactor.Dsl.Create`](Ash.Reactor.Dsl.Create.html) ### [](dsl-ash-reactor.html#reactor-destroy)reactor.destroy ``` destroy name, resource, action \\ nil ``` Declares a step that will call a destroy action on a resource. #### Undo behaviour This step has three different modes of undo. - `never` - The result of the action is never undone. This is the default. - `always` - The `undo_action` will always be called. - `outside_transaction` - The `undo_action` will not be called when running inside a `transaction` block, but will be otherwise. ### [](dsl-ash-reactor.html#nested-dsls-6)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-destroy-actor) - [context](dsl-ash-reactor.html#reactor-destroy-context) - [inputs](dsl-ash-reactor.html#reactor-destroy-inputs) - [load](dsl-ash-reactor.html#reactor-destroy-load) - [tenant](dsl-ash-reactor.html#reactor-destroy-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-destroy-wait_for) ### [](dsl-ash-reactor.html#examples-15)Examples ``` destroy :delete_post, MyApp.Post, :destroy do initial input(:post) actor result(:get_user) tenant result(:get_organisation, [:id]) end ``` ### [](dsl-ash-reactor.html#arguments-31)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-destroy-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-destroy-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-destroy-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-32)Options NameTypeDefaultDocs[`initial`](dsl-ash-reactor.html#reactor-destroy-initial)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`The record to update.[`return_destroyed?`](dsl-ash-reactor.html#reactor-destroy-return_destroyed?)`boolean``false`Whether or not the step should return the destroyed record upon completion.[`domain`](dsl-ash-reactor.html#reactor-destroy-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-destroy-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-destroy-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-destroy-description)`String.t`A description for the step[`undo_action`](dsl-ash-reactor.html#reactor-destroy-undo_action)`atom`The name of the action to call on the resource when the step is to be undone.[`undo`](dsl-ash-reactor.html#reactor-destroy-undo)`:always | :never | :outside_transaction``:never`How to handle undoing this action ### [](dsl-ash-reactor.html#reactor-destroy-actor)reactor.destroy.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-32)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-destroy-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-33)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-destroy-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-31)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-destroy-context)reactor.destroy.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-33)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-destroy-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-34)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-destroy-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-32)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-destroy-inputs)reactor.destroy.inputs ``` inputs template ``` Specify the inputs for an action ### [](dsl-ash-reactor.html#examples-16)Examples ``` inputs %{ author: result(:get_user), title: input(:title), body: input(:body) } ``` ``` inputs(author: result(:get_user)) ``` ### [](dsl-ash-reactor.html#arguments-34)Arguments NameTypeDefaultDocs[`template`](dsl-ash-reactor.html#reactor-destroy-inputs-template)`%{optional(atom) => Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value} | keyword(Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value)` ### [](dsl-ash-reactor.html#options-35)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-destroy-inputs-transform)`(any -> any) | module | nil`An optional transformation function which will transform the inputs before executing the action. ### [](dsl-ash-reactor.html#introspection-33)Introspection Target: [`Ash.Reactor.Dsl.Inputs`](Ash.Reactor.Dsl.Inputs.html) ### [](dsl-ash-reactor.html#reactor-destroy-load)reactor.destroy.load ``` load source ``` Allows the addition of an Ash load statement to the action ### [](dsl-ash-reactor.html#arguments-35)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-destroy-load-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the load ### [](dsl-ash-reactor.html#options-36)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-destroy-load-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the load before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-34)Introspection Target: [`Ash.Reactor.Dsl.ActionLoad`](Ash.Reactor.Dsl.ActionLoad.html) ### [](dsl-ash-reactor.html#reactor-destroy-tenant)reactor.destroy.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-36)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-destroy-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-37)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-destroy-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-35)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-destroy-wait_for)reactor.destroy.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-17)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-37)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-destroy-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-38)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-destroy-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-36)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-37)Introspection Target: [`Ash.Reactor.Dsl.Destroy`](Ash.Reactor.Dsl.Destroy.html) ### [](dsl-ash-reactor.html#reactor-load)reactor.load ``` load name, records, load ``` Declares a step that will load additional data on a resource. ### [](dsl-ash-reactor.html#nested-dsls-7)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-load-actor) - [context](dsl-ash-reactor.html#reactor-load-context) - [tenant](dsl-ash-reactor.html#reactor-load-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-load-wait_for) ### [](dsl-ash-reactor.html#arguments-38)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-load-name)`atom`A unique name for the step.[`records`](dsl-ash-reactor.html#reactor-load-records)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`The records upon which to add extra loaded data[`load`](dsl-ash-reactor.html#reactor-load-load)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`An Ash load statement ### [](dsl-ash-reactor.html#options-39)Options NameTypeDefaultDocs[`domain`](dsl-ash-reactor.html#reactor-load-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-load-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-load-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-load-description)`String.t`A description for the step[`transform`](dsl-ash-reactor.html#reactor-load-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the load statement before it is passed to the load.[`lazy?`](dsl-ash-reactor.html#reactor-load-lazy?)`boolean`If set to true, values will only be loaded if the related value isn't currently loaded.[`reuse_values?`](dsl-ash-reactor.html#reactor-load-reuse_values?)`boolean`Whether calculations are allowed to reuse values that have already been loaded, or must refetch them from the data layer.[`strict?`](dsl-ash-reactor.html#reactor-load-strict?)`boolean`If set to true, only specified attributes will be loaded when passing a list of fields to fetch on a relationship, which allows for more optimized data-fetching. ### [](dsl-ash-reactor.html#reactor-load-actor)reactor.load.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-39)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-load-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-40)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-load-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-38)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-load-context)reactor.load.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-40)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-load-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-41)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-load-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-39)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-load-tenant)reactor.load.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-41)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-load-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-42)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-load-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-40)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-load-wait_for)reactor.load.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-18)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-42)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-load-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-43)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-load-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-41)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-42)Introspection Target: [`Ash.Reactor.Dsl.Load`](Ash.Reactor.Dsl.Load.html) ### [](dsl-ash-reactor.html#reactor-read_one)reactor.read\_one ``` read_one name, resource, action \\ nil ``` Declares a step that will call a read action on a resource returning a single record. ### [](dsl-ash-reactor.html#nested-dsls-8)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-read_one-actor) - [context](dsl-ash-reactor.html#reactor-read_one-context) - [inputs](dsl-ash-reactor.html#reactor-read_one-inputs) - [load](dsl-ash-reactor.html#reactor-read_one-load) - [tenant](dsl-ash-reactor.html#reactor-read_one-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-read_one-wait_for) ### [](dsl-ash-reactor.html#examples-19)Examples ``` read_one :post_by_id, MyApp.Post, :read do inputs %{id: input(:post_id)} end ``` ### [](dsl-ash-reactor.html#arguments-43)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-read_one-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-read_one-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-read_one-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-44)Options NameTypeDefaultDocs[`fail_on_not_found?`](dsl-ash-reactor.html#reactor-read_one-fail_on_not_found?)`boolean``false`When set to true the step will fail if the resource is not found.[`domain`](dsl-ash-reactor.html#reactor-read_one-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-read_one-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-read_one-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-read_one-description)`String.t`A description for the step ### [](dsl-ash-reactor.html#reactor-read_one-actor)reactor.read\_one.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-44)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-read_one-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-45)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read_one-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-43)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-read_one-context)reactor.read\_one.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-45)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-read_one-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-46)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read_one-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-44)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-read_one-inputs)reactor.read\_one.inputs ``` inputs template ``` Specify the inputs for an action ### [](dsl-ash-reactor.html#examples-20)Examples ``` inputs %{ author: result(:get_user), title: input(:title), body: input(:body) } ``` ``` inputs(author: result(:get_user)) ``` ### [](dsl-ash-reactor.html#arguments-46)Arguments NameTypeDefaultDocs[`template`](dsl-ash-reactor.html#reactor-read_one-inputs-template)`%{optional(atom) => Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value} | keyword(Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value)` ### [](dsl-ash-reactor.html#options-47)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read_one-inputs-transform)`(any -> any) | module | nil`An optional transformation function which will transform the inputs before executing the action. ### [](dsl-ash-reactor.html#introspection-45)Introspection Target: [`Ash.Reactor.Dsl.Inputs`](Ash.Reactor.Dsl.Inputs.html) ### [](dsl-ash-reactor.html#reactor-read_one-load)reactor.read\_one.load ``` load source ``` Allows the addition of an Ash load statement to the action ### [](dsl-ash-reactor.html#arguments-47)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-read_one-load-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the load ### [](dsl-ash-reactor.html#options-48)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read_one-load-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the load before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-46)Introspection Target: [`Ash.Reactor.Dsl.ActionLoad`](Ash.Reactor.Dsl.ActionLoad.html) ### [](dsl-ash-reactor.html#reactor-read_one-tenant)reactor.read\_one.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-48)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-read_one-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-49)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read_one-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-47)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-read_one-wait_for)reactor.read\_one.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-21)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-49)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-read_one-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-50)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-read_one-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-48)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-49)Introspection Target: [`Ash.Reactor.Dsl.ReadOne`](Ash.Reactor.Dsl.ReadOne.html) ### [](dsl-ash-reactor.html#reactor-read)reactor.read ``` read name, resource, action \\ nil ``` Declares a step that will call a read action on a resource. ### [](dsl-ash-reactor.html#nested-dsls-9)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-read-actor) - [context](dsl-ash-reactor.html#reactor-read-context) - [inputs](dsl-ash-reactor.html#reactor-read-inputs) - [load](dsl-ash-reactor.html#reactor-read-load) - [tenant](dsl-ash-reactor.html#reactor-read-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-read-wait_for) ### [](dsl-ash-reactor.html#examples-22)Examples ``` read :read_posts, MyApp.Post, :read ``` ``` read :read_posts_in_range, MyApp.Post, :read_in_range do inputs %{min_date: input(:min_date), max_date: input(:max_date)} end ``` ### [](dsl-ash-reactor.html#arguments-50)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-read-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-read-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-read-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-51)Options NameTypeDefaultDocs[`domain`](dsl-ash-reactor.html#reactor-read-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-read-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-read-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-read-description)`String.t`A description for the step ### [](dsl-ash-reactor.html#reactor-read-actor)reactor.read.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-51)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-read-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-52)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-50)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-read-context)reactor.read.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-52)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-read-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-53)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-51)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-read-inputs)reactor.read.inputs ``` inputs template ``` Specify the inputs for an action ### [](dsl-ash-reactor.html#examples-23)Examples ``` inputs %{ author: result(:get_user), title: input(:title), body: input(:body) } ``` ``` inputs(author: result(:get_user)) ``` ### [](dsl-ash-reactor.html#arguments-53)Arguments NameTypeDefaultDocs[`template`](dsl-ash-reactor.html#reactor-read-inputs-template)`%{optional(atom) => Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value} | keyword(Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value)` ### [](dsl-ash-reactor.html#options-54)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read-inputs-transform)`(any -> any) | module | nil`An optional transformation function which will transform the inputs before executing the action. ### [](dsl-ash-reactor.html#introspection-52)Introspection Target: [`Ash.Reactor.Dsl.Inputs`](Ash.Reactor.Dsl.Inputs.html) ### [](dsl-ash-reactor.html#reactor-read-load)reactor.read.load ``` load source ``` Allows the addition of an Ash load statement to the action ### [](dsl-ash-reactor.html#arguments-54)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-read-load-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the load ### [](dsl-ash-reactor.html#options-55)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read-load-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the load before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-53)Introspection Target: [`Ash.Reactor.Dsl.ActionLoad`](Ash.Reactor.Dsl.ActionLoad.html) ### [](dsl-ash-reactor.html#reactor-read-tenant)reactor.read.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-55)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-read-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-56)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-read-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-54)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-read-wait_for)reactor.read.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-24)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-56)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-read-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-57)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-read-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-55)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-56)Introspection Target: [`Ash.Reactor.Dsl.Read`](Ash.Reactor.Dsl.Read.html) ### [](dsl-ash-reactor.html#reactor-transaction)reactor.transaction ``` transaction name, resources ``` Creates a group of steps which will be executed inside a data layer transaction. ### [](dsl-ash-reactor.html#nested-dsls-10)Nested DSLs - [wait\_for](dsl-ash-reactor.html#reactor-transaction-wait_for) ### [](dsl-ash-reactor.html#arguments-57)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-transaction-name)`atom`A unique name for the step.[`resources`](dsl-ash-reactor.html#reactor-transaction-resources)`module | list(module)`A resource or list of resources to consider in the transaction. ### [](dsl-ash-reactor.html#options-58)Options NameTypeDefaultDocs[`return`](dsl-ash-reactor.html#reactor-transaction-return)`atom`The name of the step whose result will be returned as the return value of the transaction.[`timeout`](dsl-ash-reactor.html#reactor-transaction-timeout)`pos_integer | :infinity``15000`How long to allow the transaction to run before timing out. ### [](dsl-ash-reactor.html#reactor-transaction-wait_for)reactor.transaction.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-25)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-58)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-transaction-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-59)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-transaction-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-57)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-58)Introspection Target: [`Ash.Reactor.Dsl.Transaction`](Ash.Reactor.Dsl.Transaction.html) ### [](dsl-ash-reactor.html#reactor-update)reactor.update ``` update name, resource, action \\ nil ``` Declares a step that will call an update action on a resource. #### Undo behaviour This step has three different modes of undo. - `never` - The result of the action is never undone. This is the default. - `always` - The `undo_action` will always be called. - `outside_transaction` - The `undo_action` will not be called when running inside a `transaction` block, but will be otherwise. ### [](dsl-ash-reactor.html#nested-dsls-11)Nested DSLs - [actor](dsl-ash-reactor.html#reactor-update-actor) - [context](dsl-ash-reactor.html#reactor-update-context) - [inputs](dsl-ash-reactor.html#reactor-update-inputs) - [load](dsl-ash-reactor.html#reactor-update-load) - [tenant](dsl-ash-reactor.html#reactor-update-tenant) - [wait\_for](dsl-ash-reactor.html#reactor-update-wait_for) ### [](dsl-ash-reactor.html#examples-26)Examples ``` update :publish_post, MyApp.Post, :update do initial input(:post) inputs %{ published: value(true) } actor result(:get_user) tenant result(:get_organisation, [:id]) end ``` ### [](dsl-ash-reactor.html#arguments-59)Arguments NameTypeDefaultDocs[`name`](dsl-ash-reactor.html#reactor-update-name)`atom`A unique name for the step.[`resource`](dsl-ash-reactor.html#reactor-update-resource)`module`The resource to call the action on.[`action`](dsl-ash-reactor.html#reactor-update-action)`atom`The name of the action to call on the resource. ### [](dsl-ash-reactor.html#options-60)Options NameTypeDefaultDocs[`initial`](dsl-ash-reactor.html#reactor-update-initial)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`The record to update.[`domain`](dsl-ash-reactor.html#reactor-update-domain)`module`The Domain to use when calling the action. Defaults to the Domain set on the resource or in the `ash` section.[`async?`](dsl-ash-reactor.html#reactor-update-async?)`boolean``true`When set to true the step will be executed asynchronously via Reactor's `TaskSupervisor`.[`authorize?`](dsl-ash-reactor.html#reactor-update-authorize?)`boolean | nil`Explicitly enable or disable authorization for the action.[`description`](dsl-ash-reactor.html#reactor-update-description)`String.t`A description for the step[`undo_action`](dsl-ash-reactor.html#reactor-update-undo_action)`atom`The name of the action to call on the resource when the step is to be undone.[`undo`](dsl-ash-reactor.html#reactor-update-undo)`:always | :never | :outside_transaction``:never`How to handle undoing this action ### [](dsl-ash-reactor.html#reactor-update-actor)reactor.update.actor ``` actor source ``` Specifies the action actor ### [](dsl-ash-reactor.html#arguments-60)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-update-actor-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the actor. ### [](dsl-ash-reactor.html#options-61)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-update-actor-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the actor before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-59)Introspection Target: [`Ash.Reactor.Dsl.Actor`](Ash.Reactor.Dsl.Actor.html) ### [](dsl-ash-reactor.html#reactor-update-context)reactor.update.context ``` context context ``` A map to be merged into the action's context ### [](dsl-ash-reactor.html#arguments-61)Arguments NameTypeDefaultDocs[`context`](dsl-ash-reactor.html#reactor-update-context-context)`nil | Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value | map`A map to be merged into the action's context. ### [](dsl-ash-reactor.html#options-62)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-update-context-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the context before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-60)Introspection Target: [`Ash.Reactor.Dsl.Context`](Ash.Reactor.Dsl.Context.html) ### [](dsl-ash-reactor.html#reactor-update-inputs)reactor.update.inputs ``` inputs template ``` Specify the inputs for an action ### [](dsl-ash-reactor.html#examples-27)Examples ``` inputs %{ author: result(:get_user), title: input(:title), body: input(:body) } ``` ``` inputs(author: result(:get_user)) ``` ### [](dsl-ash-reactor.html#arguments-62)Arguments NameTypeDefaultDocs[`template`](dsl-ash-reactor.html#reactor-update-inputs-template)`%{optional(atom) => Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value} | keyword(Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value)` ### [](dsl-ash-reactor.html#options-63)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-update-inputs-transform)`(any -> any) | module | nil`An optional transformation function which will transform the inputs before executing the action. ### [](dsl-ash-reactor.html#introspection-61)Introspection Target: [`Ash.Reactor.Dsl.Inputs`](Ash.Reactor.Dsl.Inputs.html) ### [](dsl-ash-reactor.html#reactor-update-load)reactor.update.load ``` load source ``` Allows the addition of an Ash load statement to the action ### [](dsl-ash-reactor.html#arguments-63)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-update-load-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the load ### [](dsl-ash-reactor.html#options-64)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-update-load-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the load before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-62)Introspection Target: [`Ash.Reactor.Dsl.ActionLoad`](Ash.Reactor.Dsl.ActionLoad.html) ### [](dsl-ash-reactor.html#reactor-update-tenant)reactor.update.tenant ``` tenant source ``` Specifies the action tenant ### [](dsl-ash-reactor.html#arguments-64)Arguments NameTypeDefaultDocs[`source`](dsl-ash-reactor.html#reactor-update-tenant-source)`Reactor.Template.Element | Reactor.Template.Input | Reactor.Template.Result | Reactor.Template.Value`What to use as the source of the tenant. ### [](dsl-ash-reactor.html#options-65)Options NameTypeDefaultDocs[`transform`](dsl-ash-reactor.html#reactor-update-tenant-transform)`(any -> any) | module | nil`An optional transformation function which can be used to modify the tenant before it is passed to the action. ### [](dsl-ash-reactor.html#introspection-63)Introspection Target: [`Ash.Reactor.Dsl.Tenant`](Ash.Reactor.Dsl.Tenant.html) ### [](dsl-ash-reactor.html#reactor-update-wait_for)reactor.update.wait\_for ``` wait_for names ``` Wait for the named step to complete before allowing this one to start. Desugars to `argument :_, result(step_to_wait_for)` ### [](dsl-ash-reactor.html#examples-28)Examples ``` wait_for :create_user ``` ### [](dsl-ash-reactor.html#arguments-65)Arguments NameTypeDefaultDocs[`names`](dsl-ash-reactor.html#reactor-update-wait_for-names)`atom | list(atom)`The name of the step to wait for. ### [](dsl-ash-reactor.html#options-66)Options NameTypeDefaultDocs[`description`](dsl-ash-reactor.html#reactor-update-wait_for-description)`String.t`An optional description. ### [](dsl-ash-reactor.html#introspection-64)Introspection Target: [`Reactor.Dsl.WaitFor`](../reactor/0.10.3/Reactor.Dsl.WaitFor.html) ### [](dsl-ash-reactor.html#introspection-65)Introspection Target: [`Ash.Reactor.Dsl.Update`](Ash.Reactor.Dsl.Update.html) [← Previous Page Ash.DataLayer.Mnesia](dsl-ash-datalayer-mnesia.html) [Next Page → Glossary](glossary.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/dsls/DSL-Ash.Reactor.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Ash.Resource [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/dsls/DSL-Ash.Resource.md#L1 "View Source") ## [](dsl-ash-resource.html#attributes)attributes A section for declaring attributes on the resource. ### [](dsl-ash-resource.html#nested-dsls)Nested DSLs - [attribute](dsl-ash-resource.html#attributes-attribute) - [create\_timestamp](dsl-ash-resource.html#attributes-create_timestamp) - [update\_timestamp](dsl-ash-resource.html#attributes-update_timestamp) - [integer\_primary\_key](dsl-ash-resource.html#attributes-integer_primary_key) - [uuid\_primary\_key](dsl-ash-resource.html#attributes-uuid_primary_key) - [uuid\_v7\_primary\_key](dsl-ash-resource.html#attributes-uuid_v7_primary_key) ### [](dsl-ash-resource.html#examples)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 ``` ### [](dsl-ash-resource.html#attributes-attribute)attributes.attribute ``` attribute name, type ``` Declares an attribute on the resource. ### [](dsl-ash-resource.html#examples-1)Examples ``` attribute :name, :string do allow_nil? false end ``` ### [](dsl-ash-resource.html#arguments)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#attributes-attribute-name)`atom`The name of the attribute.[`type`](dsl-ash-resource.html#attributes-attribute-type)`module`The type of the attribute. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options)Options NameTypeDefaultDocs[`constraints`](dsl-ash-resource.html#attributes-attribute-constraints)`keyword`Constraints to provide to the type when casting the value. For more, see [`Ash.Type`](Ash.Type.html).[`description`](dsl-ash-resource.html#attributes-attribute-description)`String.t`An optional description for the attribute.[`sensitive?`](dsl-ash-resource.html#attributes-attribute-sensitive?)`boolean``false`Whether or not the attribute value contains sensitive information, like PII(Personally Identifiable Information). See the [Sensitive Data guide](sensitive-data.html) for more.[`source`](dsl-ash-resource.html#attributes-attribute-source)`atom`If the field should be mapped to a different name in the data layer. Support varies by data layer.[`select_by_default?`](dsl-ash-resource.html#attributes-attribute-select_by_default?)`boolean``true`Whether or not the attribute is selected by default.[`always_select?`](dsl-ash-resource.html#attributes-attribute-always_select?)`boolean``false`Whether or not to ensure this attribute is always selected when reading from the database, regardless of applied select statements.[`primary_key?`](dsl-ash-resource.html#attributes-attribute-primary_key?)`boolean``false`Whether the attribute is the primary key. Composite primary key is also possible by using `primary_key? true` in more than one attribute. If primary\_key? is true, allow\_nil? must be false.[`allow_nil?`](dsl-ash-resource.html#attributes-attribute-allow_nil?)`boolean``true`Whether or not the attribute can be set to nil. If nil value is given error is raised.[`generated?`](dsl-ash-resource.html#attributes-attribute-generated?)`boolean``false`Whether or not the value may be generated by the data layer.[`writable?`](dsl-ash-resource.html#attributes-attribute-writable?)`boolean``true`Whether or not the value can be written to. Non-writable attributes can still be written with [`Ash.Changeset.force_change_attribute/3`](Ash.Changeset.html#force_change_attribute/3).[`public?`](dsl-ash-resource.html#attributes-attribute-public?)`boolean``false`Whether or not the attribute should be shown over public interfaces. See the [sensitive data guide](sensitive-data.html) for more.[`default`](dsl-ash-resource.html#attributes-attribute-default)`(-> any) | mfa | any`A value to be set on all creates, unless a value is being provided already. Note: The default value is casted according to the type's `Ash.Type.*` module, before it is saved. For `:string`, for example, if `constraints: [allow_empty?: _]` is false, the value `""` will be cast to `nil`. See the `:constraints` option, the `:allow_nil?` option, and the relevant `Ash.Type.*` documentation.[`update_default`](dsl-ash-resource.html#attributes-attribute-update_default)`(-> any) | mfa | any`A value to be set on all updates, unless a value is being provided already.[`filterable?`](dsl-ash-resource.html#attributes-attribute-filterable?)`boolean | :simple_equality``true`Whether or not the attribute can be referenced in filters.[`sortable?`](dsl-ash-resource.html#attributes-attribute-sortable?)`boolean``true`Whether or not the attribute can be referenced in sorts.[`match_other_defaults?`](dsl-ash-resource.html#attributes-attribute-match_other_defaults?)`boolean``false`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. ### [](dsl-ash-resource.html#introspection)Introspection Target: [`Ash.Resource.Attribute`](Ash.Resource.Attribute.html) ### [](dsl-ash-resource.html#attributes-create_timestamp)attributes.create\_timestamp ``` create_timestamp name ``` Declares a non-writable attribute with a create default of `&DateTime.utc_now/0` Accepts all the same options as `Ash.Resource.Dsl.attributes.attribute`, except it sets the following different defaults: ``` writable? false default &DateTime.utc_now/0 match_other_defaults? true type Ash.Type.UTCDatetimeUsec allow_nil? false ``` ### [](dsl-ash-resource.html#examples-2)Examples ``` create_timestamp :inserted_at ``` ### [](dsl-ash-resource.html#arguments-1)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#attributes-create_timestamp-name)`atom`The name of the attribute. ### [](dsl-ash-resource.html#introspection-1)Introspection Target: [`Ash.Resource.Attribute`](Ash.Resource.Attribute.html) ### [](dsl-ash-resource.html#attributes-update_timestamp)attributes.update\_timestamp ``` update_timestamp name ``` Declares a non-writable attribute with a create and update default of `&DateTime.utc_now/0` Accepts all the same options as `Ash.Resource.Dsl.attributes.attribute`, except it sets the following different defaults: ``` writable? false default &DateTime.utc_now/0 match_other_defaults? true update_default &DateTime.utc_now/0 type Ash.Type.UTCDatetimeUsec allow_nil? false ``` ### [](dsl-ash-resource.html#examples-3)Examples ``` update_timestamp :updated_at ``` ### [](dsl-ash-resource.html#arguments-2)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#attributes-update_timestamp-name)`atom`The name of the attribute. ### [](dsl-ash-resource.html#introspection-2)Introspection Target: [`Ash.Resource.Attribute`](Ash.Resource.Attribute.html) ### [](dsl-ash-resource.html#attributes-integer_primary_key)attributes.integer\_primary\_key ``` integer_primary_key name ``` Declares a generated, non writable, non-nil, primary key column of type integer. Generated integer primary keys must be supported by the data layer. Accepts all the same options as `Ash.Resource.Dsl.attributes.attribute`, except for `allow_nil?`, but it sets the following different defaults: ``` public? true writable? false primary_key? true generated? true type :integer ``` ### [](dsl-ash-resource.html#examples-4)Examples ``` integer_primary_key :id ``` ### [](dsl-ash-resource.html#arguments-3)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#attributes-integer_primary_key-name)`atom`The name of the attribute. ### [](dsl-ash-resource.html#introspection-3)Introspection Target: [`Ash.Resource.Attribute`](Ash.Resource.Attribute.html) ### [](dsl-ash-resource.html#attributes-uuid_primary_key)attributes.uuid\_primary\_key ``` uuid_primary_key name ``` Declares a non writable, non-nil, primary key column of type `uuid`, which defaults to [`Ash.UUID.generate/0`](Ash.UUID.html#generate/0). Accepts all the same options as `Ash.Resource.Dsl.attributes.attribute`, except for `allow_nil?`, but it sets the following different defaults: ``` writable? false public? true default &Ash.UUID.generate/0 primary_key? true type :uuid ``` ### [](dsl-ash-resource.html#examples-5)Examples ``` uuid_primary_key :id ``` ### [](dsl-ash-resource.html#arguments-4)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#attributes-uuid_primary_key-name)`atom`The name of the attribute. ### [](dsl-ash-resource.html#introspection-4)Introspection Target: [`Ash.Resource.Attribute`](Ash.Resource.Attribute.html) ### [](dsl-ash-resource.html#attributes-uuid_v7_primary_key)attributes.uuid\_v7\_primary\_key ``` uuid_v7_primary_key name ``` Declares a non writable, non-nil, primary key column of type `uuid_v7`, which defaults to [`Ash.UUIDv7.generate/0`](Ash.UUIDv7.html#generate/0). Accepts all the same options as `Ash.Resource.Dsl.attributes.attribute`, except for `allow_nil?`, but it sets the following different defaults: ``` writable? false public? true default &Ash.UUIDv7.generate/0 primary_key? true type :uuid_v7 ``` ### [](dsl-ash-resource.html#examples-6)Examples ``` uuid_v7_primary_key :id ``` ### [](dsl-ash-resource.html#arguments-5)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#attributes-uuid_v7_primary_key-name)`atom`The name of the attribute. ### [](dsl-ash-resource.html#introspection-5)Introspection Target: [`Ash.Resource.Attribute`](Ash.Resource.Attribute.html) ## [](dsl-ash-resource.html#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`](Ash.Query.html#load/2)). See the [relationships guide](relationships.html) for more. ### [](dsl-ash-resource.html#nested-dsls-1)Nested DSLs - [has\_one](dsl-ash-resource.html#relationships-has_one) - filter - [has\_many](dsl-ash-resource.html#relationships-has_many) - filter - [many\_to\_many](dsl-ash-resource.html#relationships-many_to_many) - filter - [belongs\_to](dsl-ash-resource.html#relationships-belongs_to) - filter ### [](dsl-ash-resource.html#examples-7)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 ``` ### [](dsl-ash-resource.html#relationships-has_one)relationships.has\_one ``` has_one name, destination ``` 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. See the [relationships guide](relationships.html) for more. ### [](dsl-ash-resource.html#nested-dsls-2)Nested DSLs - [filter](dsl-ash-resource.html#relationships-has_one-filter) ### [](dsl-ash-resource.html#examples-8)Examples ``` # In a resource called `Word` has_one :dictionary_entry, DictionaryEntry do source_attribute :text destination_attribute :word_text end ``` ### [](dsl-ash-resource.html#arguments-6)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#relationships-has_one-name)`atom`The name of the relationship[`destination`](dsl-ash-resource.html#relationships-has_one-destination)`module`The destination resource ### [](dsl-ash-resource.html#options-1)Options NameTypeDefaultDocs[`manual`](dsl-ash-resource.html#relationships-has_one-manual)`(any, any -> any) | module`A module that implements [`Ash.Resource.ManualRelationship`](Ash.Resource.ManualRelationship.html). Also accepts a 2 argument function that takes the source records and the context.[`no_attributes?`](dsl-ash-resource.html#relationships-has_one-no_attributes?)`boolean`All existing entities are considered related, i.e this relationship is not based on any fields, and `source_attribute` and `destination_attribute` are ignored. See the See the [relationships guide](relationships.html) for more.[`allow_nil?`](dsl-ash-resource.html#relationships-has_one-allow_nil?)`boolean``true`Marks the relationship as required. Has no effect on validations, but can inform extensions that there will always be a related entity.[`from_many?`](dsl-ash-resource.html#relationships-has_one-from_many?)`boolean``false`Signal that this relationship is actually a `has_many` where the first record is given via the `sort`. This will allow data layers to properly deduplicate when necessary.[`description`](dsl-ash-resource.html#relationships-has_one-description)`String.t`An optional description for the relationship[`destination_attribute`](dsl-ash-resource.html#relationships-has_one-destination_attribute)`atom`The attribute on the related resource that should match the `source_attribute` configured on this resource.[`validate_destination_attribute?`](dsl-ash-resource.html#relationships-has_one-validate_destination_attribute?)`boolean``true`Whether or not to validate that the destination field exists on the destination resource[`source_attribute`](dsl-ash-resource.html#relationships-has_one-source_attribute)`atom``:id`The field on this resource that should match the `destination_attribute` on the related resource.[`relationship_context`](dsl-ash-resource.html#relationships-has_one-relationship_context)`any`Context to be set on any queries or changesets generated for managing or querying this relationship.[`public?`](dsl-ash-resource.html#relationships-has_one-public?)`boolean``false`Whether or not the relationship will appear in public interfaces[`not_found_message`](dsl-ash-resource.html#relationships-has_one-not_found_message)`String.t`A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.[`writable?`](dsl-ash-resource.html#relationships-has_one-writable?)`boolean``true`Whether or not the relationship may be managed.[`read_action`](dsl-ash-resource.html#relationships-has_one-read_action)`atom`The read action on the destination resource to use when loading data and filtering.[`domain`](dsl-ash-resource.html#relationships-has_one-domain)`atom`The domain module to use when working with the related entity.[`filterable?`](dsl-ash-resource.html#relationships-has_one-filterable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sortable?`](dsl-ash-resource.html#relationships-has_one-sortable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sort`](dsl-ash-resource.html#relationships-has_one-sort)`any`A sort statement to be applied when loading the relationship.[`could_be_related_at_creation?`](dsl-ash-resource.html#relationships-has_one-could_be_related_at_creation?)`boolean``false`Whether or not related values may exist for this relationship at creation.[`violation_message`](dsl-ash-resource.html#relationships-has_one-violation_message)`String.t`A message to show if there is a conflict with this relationship in the database on destroy.[`authorize_read_with`](dsl-ash-resource.html#relationships-has_one-authorize_read_with)`:error | :filter`If set to `:error`, any authorization filter added to the relationship will result in an error if any record matches the filter in the database.[`allow_forbidden_field?`](dsl-ash-resource.html#relationships-has_one-allow_forbidden_field?)`boolean``false`If set to `true`, the relationship will be set to `%Ash.ForbiddenField{}` if its query produces a forbidden error. ### [](dsl-ash-resource.html#relationships-has_one-filter)relationships.has\_one.filter ``` filter filter ``` Applies a filter. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#examples-9)Examples ``` filter expr(first_name == "fred") filter expr(last_name == "weasley" and magician == true) ``` ### [](dsl-ash-resource.html#arguments-7)Arguments NameTypeDefaultDocs[`filter`](dsl-ash-resource.html#relationships-has_one-filter-filter)`any`The filter to apply. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#introspection-6)Introspection Target: [`Ash.Resource.Dsl.Filter`](Ash.Resource.Dsl.Filter.html) ### [](dsl-ash-resource.html#introspection-7)Introspection Target: [`Ash.Resource.Relationships.HasOne`](Ash.Resource.Relationships.HasOne.html) ### [](dsl-ash-resource.html#relationships-has_many)relationships.has\_many ``` has_many name, destination ``` Declares a `has_many` relationship. There can be any number of related entities. See the [relationships guide](relationships.html) for more. ### [](dsl-ash-resource.html#nested-dsls-3)Nested DSLs - [filter](dsl-ash-resource.html#relationships-has_many-filter) ### [](dsl-ash-resource.html#examples-10)Examples ``` # In a resource called `Word` has_many :definitions, DictionaryDefinition do source_attribute :text destination_attribute :word_text end ``` ### [](dsl-ash-resource.html#arguments-8)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#relationships-has_many-name)`atom`The name of the relationship[`destination`](dsl-ash-resource.html#relationships-has_many-destination)`module`The destination resource ### [](dsl-ash-resource.html#options-2)Options NameTypeDefaultDocs[`manual`](dsl-ash-resource.html#relationships-has_many-manual)`(any, any -> any) | module`A module that implements [`Ash.Resource.ManualRelationship`](Ash.Resource.ManualRelationship.html). Also accepts a 2 argument function that takes the source records and the context.[`no_attributes?`](dsl-ash-resource.html#relationships-has_many-no_attributes?)`boolean`All existing entities are considered related, i.e this relationship is not based on any fields, and `source_attribute` and `destination_attribute` are ignored. See the See the [relationships guide](relationships.html) for more.[`description`](dsl-ash-resource.html#relationships-has_many-description)`String.t`An optional description for the relationship[`destination_attribute`](dsl-ash-resource.html#relationships-has_many-destination_attribute)`atom`The attribute on the related resource that should match the `source_attribute` configured on this resource.[`validate_destination_attribute?`](dsl-ash-resource.html#relationships-has_many-validate_destination_attribute?)`boolean``true`Whether or not to validate that the destination field exists on the destination resource[`source_attribute`](dsl-ash-resource.html#relationships-has_many-source_attribute)`atom``:id`The field on this resource that should match the `destination_attribute` on the related resource.[`relationship_context`](dsl-ash-resource.html#relationships-has_many-relationship_context)`any`Context to be set on any queries or changesets generated for managing or querying this relationship.[`public?`](dsl-ash-resource.html#relationships-has_many-public?)`boolean``false`Whether or not the relationship will appear in public interfaces[`not_found_message`](dsl-ash-resource.html#relationships-has_many-not_found_message)`String.t`A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.[`writable?`](dsl-ash-resource.html#relationships-has_many-writable?)`boolean``true`Whether or not the relationship may be managed.[`read_action`](dsl-ash-resource.html#relationships-has_many-read_action)`atom`The read action on the destination resource to use when loading data and filtering.[`domain`](dsl-ash-resource.html#relationships-has_many-domain)`atom`The domain module to use when working with the related entity.[`filterable?`](dsl-ash-resource.html#relationships-has_many-filterable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sortable?`](dsl-ash-resource.html#relationships-has_many-sortable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sort`](dsl-ash-resource.html#relationships-has_many-sort)`any`A sort statement to be applied when loading the relationship.[`could_be_related_at_creation?`](dsl-ash-resource.html#relationships-has_many-could_be_related_at_creation?)`boolean``false`Whether or not related values may exist for this relationship at creation.[`violation_message`](dsl-ash-resource.html#relationships-has_many-violation_message)`String.t`A message to show if there is a conflict with this relationship in the database on destroy.[`authorize_read_with`](dsl-ash-resource.html#relationships-has_many-authorize_read_with)`:error | :filter`If set to `:error`, any authorization filter added to the relationship will result in an error if any record matches the filter in the database.[`allow_forbidden_field?`](dsl-ash-resource.html#relationships-has_many-allow_forbidden_field?)`boolean``false`If set to `true`, the relationship will be set to `%Ash.ForbiddenField{}` if its query produces a forbidden error. ### [](dsl-ash-resource.html#relationships-has_many-filter)relationships.has\_many.filter ``` filter filter ``` Applies a filter. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#examples-11)Examples ``` filter expr(first_name == "fred") filter expr(last_name == "weasley" and magician == true) ``` ### [](dsl-ash-resource.html#arguments-9)Arguments NameTypeDefaultDocs[`filter`](dsl-ash-resource.html#relationships-has_many-filter-filter)`any`The filter to apply. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#introspection-8)Introspection Target: [`Ash.Resource.Dsl.Filter`](Ash.Resource.Dsl.Filter.html) ### [](dsl-ash-resource.html#introspection-9)Introspection Target: [`Ash.Resource.Relationships.HasMany`](Ash.Resource.Relationships.HasMany.html) ### [](dsl-ash-resource.html#relationships-many_to_many)relationships.many\_to\_many ``` many_to_many name, destination ``` 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. See the [relationships guide](relationships.html) for more. ### [](dsl-ash-resource.html#nested-dsls-4)Nested DSLs - [filter](dsl-ash-resource.html#relationships-many_to_many-filter) ### [](dsl-ash-resource.html#examples-12)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 ``` ### [](dsl-ash-resource.html#arguments-10)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#relationships-many_to_many-name)`atom`The name of the relationship[`destination`](dsl-ash-resource.html#relationships-many_to_many-destination)`module`The destination resource ### [](dsl-ash-resource.html#options-3)Options NameTypeDefaultDocs[`source_attribute_on_join_resource`](dsl-ash-resource.html#relationships-many_to_many-source_attribute_on_join_resource)`atom`The attribute on the join resource that should line up with `source_attribute` on this resource. Defaults to `<snake_cased_last_part_of_source_module_name>_id`.[`destination_attribute_on_join_resource`](dsl-ash-resource.html#relationships-many_to_many-destination_attribute_on_join_resource)`atom`The attribute on the join resource that should line up with `destination_attribute` on the related resource. Defaults to `<snake_cased_last_part_of_destination_module_name>_id`.[`through`](dsl-ash-resource.html#relationships-many_to_many-through)`module`The resource to use as the join resource.[`join_relationship`](dsl-ash-resource.html#relationships-many_to_many-join_relationship)`atom`The has\_many relationship to the join resource. Defaults to `<relationship_name>_join_assoc`.[`description`](dsl-ash-resource.html#relationships-many_to_many-description)`String.t`An optional description for the relationship[`destination_attribute`](dsl-ash-resource.html#relationships-many_to_many-destination_attribute)`atom``:id`The attribute on the related resource that should match the `source_attribute` configured on this resource.[`validate_destination_attribute?`](dsl-ash-resource.html#relationships-many_to_many-validate_destination_attribute?)`boolean``true`Whether or not to validate that the destination field exists on the destination resource[`source_attribute`](dsl-ash-resource.html#relationships-many_to_many-source_attribute)`atom``:id`The field on this resource that should match the `destination_attribute` on the related resource.[`relationship_context`](dsl-ash-resource.html#relationships-many_to_many-relationship_context)`any`Context to be set on any queries or changesets generated for managing or querying this relationship.[`public?`](dsl-ash-resource.html#relationships-many_to_many-public?)`boolean``false`Whether or not the relationship will appear in public interfaces[`not_found_message`](dsl-ash-resource.html#relationships-many_to_many-not_found_message)`String.t`A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.[`writable?`](dsl-ash-resource.html#relationships-many_to_many-writable?)`boolean``true`Whether or not the relationship may be managed.[`read_action`](dsl-ash-resource.html#relationships-many_to_many-read_action)`atom`The read action on the destination resource to use when loading data and filtering.[`domain`](dsl-ash-resource.html#relationships-many_to_many-domain)`atom`The domain module to use when working with the related entity.[`filterable?`](dsl-ash-resource.html#relationships-many_to_many-filterable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sortable?`](dsl-ash-resource.html#relationships-many_to_many-sortable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sort`](dsl-ash-resource.html#relationships-many_to_many-sort)`any`A sort statement to be applied when loading the relationship.[`could_be_related_at_creation?`](dsl-ash-resource.html#relationships-many_to_many-could_be_related_at_creation?)`boolean``false`Whether or not related values may exist for this relationship at creation.[`violation_message`](dsl-ash-resource.html#relationships-many_to_many-violation_message)`String.t`A message to show if there is a conflict with this relationship in the database on destroy.[`authorize_read_with`](dsl-ash-resource.html#relationships-many_to_many-authorize_read_with)`:error | :filter`If set to `:error`, any authorization filter added to the relationship will result in an error if any record matches the filter in the database.[`allow_forbidden_field?`](dsl-ash-resource.html#relationships-many_to_many-allow_forbidden_field?)`boolean``false`If set to `true`, the relationship will be set to `%Ash.ForbiddenField{}` if its query produces a forbidden error. ### [](dsl-ash-resource.html#relationships-many_to_many-filter)relationships.many\_to\_many.filter ``` filter filter ``` Applies a filter. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#examples-13)Examples ``` filter expr(first_name == "fred") filter expr(last_name == "weasley" and magician == true) ``` ### [](dsl-ash-resource.html#arguments-11)Arguments NameTypeDefaultDocs[`filter`](dsl-ash-resource.html#relationships-many_to_many-filter-filter)`any`The filter to apply. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#introspection-10)Introspection Target: [`Ash.Resource.Dsl.Filter`](Ash.Resource.Dsl.Filter.html) ### [](dsl-ash-resource.html#introspection-11)Introspection Target: [`Ash.Resource.Relationships.ManyToMany`](Ash.Resource.Relationships.ManyToMany.html) ### [](dsl-ash-resource.html#relationships-belongs_to)relationships.belongs\_to ``` belongs_to name, destination ``` 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. See the [relationships guide](relationships.html) for more. ### [](dsl-ash-resource.html#nested-dsls-5)Nested DSLs - [filter](dsl-ash-resource.html#relationships-belongs_to-filter) ### [](dsl-ash-resource.html#examples-14)Examples ``` # In a resource called `Word` belongs_to :dictionary_entry, DictionaryEntry do source_attribute :text, destination_attribute :word_text end ``` ### [](dsl-ash-resource.html#arguments-12)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#relationships-belongs_to-name)`atom`The name of the relationship[`destination`](dsl-ash-resource.html#relationships-belongs_to-destination)`module`The destination resource ### [](dsl-ash-resource.html#options-4)Options NameTypeDefaultDocs[`primary_key?`](dsl-ash-resource.html#relationships-belongs_to-primary_key?)`boolean``false`Whether the generated attribute is, or is part of, the primary key of a resource.[`allow_nil?`](dsl-ash-resource.html#relationships-belongs_to-allow_nil?)`boolean``true`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.[`attribute_writable?`](dsl-ash-resource.html#relationships-belongs_to-attribute_writable?)`boolean`Whether the generated attribute will be marked as writable. If not set, it will default to the relationship's `writable?` setting.[`attribute_public?`](dsl-ash-resource.html#relationships-belongs_to-attribute_public?)`boolean`Whether or not the generated attribute will be public. If not set, it will default to the relationship's `public?` setting.[`define_attribute?`](dsl-ash-resource.html#relationships-belongs_to-define_attribute?)`boolean``true`If set to `false` an attribute is not created on the resource for this relationship, and one must be manually added in `attributes`, invalidating many other options.[`attribute_type`](dsl-ash-resource.html#relationships-belongs_to-attribute_type)`any``:uuid`The type of the generated created attribute. See [`Ash.Type`](Ash.Type.html) for more.[`description`](dsl-ash-resource.html#relationships-belongs_to-description)`String.t`An optional description for the relationship[`destination_attribute`](dsl-ash-resource.html#relationships-belongs_to-destination_attribute)`atom``:id`The attribute on the related resource that should match the `source_attribute` configured on this resource.[`validate_destination_attribute?`](dsl-ash-resource.html#relationships-belongs_to-validate_destination_attribute?)`boolean``true`Whether or not to validate that the destination field exists on the destination resource[`source_attribute`](dsl-ash-resource.html#relationships-belongs_to-source_attribute)`atom`The field on this resource that should match the `destination_attribute` on the related resource. - Defaults to &lt;name&gt;\_id[`relationship_context`](dsl-ash-resource.html#relationships-belongs_to-relationship_context)`any`Context to be set on any queries or changesets generated for managing or querying this relationship.[`public?`](dsl-ash-resource.html#relationships-belongs_to-public?)`boolean``false`Whether or not the relationship will appear in public interfaces[`not_found_message`](dsl-ash-resource.html#relationships-belongs_to-not_found_message)`String.t`A message to show if there is a conflict with this relationship in the database on update or create, or when managing relationships.[`writable?`](dsl-ash-resource.html#relationships-belongs_to-writable?)`boolean``true`Whether or not the relationship may be managed.[`read_action`](dsl-ash-resource.html#relationships-belongs_to-read_action)`atom`The read action on the destination resource to use when loading data and filtering.[`domain`](dsl-ash-resource.html#relationships-belongs_to-domain)`atom`The domain module to use when working with the related entity.[`filterable?`](dsl-ash-resource.html#relationships-belongs_to-filterable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sortable?`](dsl-ash-resource.html#relationships-belongs_to-sortable?)`boolean``true`If set to `false`, the relationship will not be usable in filters.[`sort`](dsl-ash-resource.html#relationships-belongs_to-sort)`any`A sort statement to be applied when loading the relationship.[`violation_message`](dsl-ash-resource.html#relationships-belongs_to-violation_message)`String.t`A message to show if there is a conflict with this relationship in the database on destroy.[`authorize_read_with`](dsl-ash-resource.html#relationships-belongs_to-authorize_read_with)`:error | :filter`If set to `:error`, any authorization filter added to the relationship will result in an error if any record matches the filter in the database.[`allow_forbidden_field?`](dsl-ash-resource.html#relationships-belongs_to-allow_forbidden_field?)`boolean``false`If set to `true`, the relationship will be set to `%Ash.ForbiddenField{}` if its query produces a forbidden error. ### [](dsl-ash-resource.html#relationships-belongs_to-filter)relationships.belongs\_to.filter ``` filter filter ``` Applies a filter. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#examples-15)Examples ``` filter expr(first_name == "fred") filter expr(last_name == "weasley" and magician == true) ``` ### [](dsl-ash-resource.html#arguments-13)Arguments NameTypeDefaultDocs[`filter`](dsl-ash-resource.html#relationships-belongs_to-filter-filter)`any`The filter to apply. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#introspection-12)Introspection Target: [`Ash.Resource.Dsl.Filter`](Ash.Resource.Dsl.Filter.html) ### [](dsl-ash-resource.html#introspection-13)Introspection Target: [`Ash.Resource.Relationships.BelongsTo`](Ash.Resource.Relationships.BelongsTo.html) ## [](dsl-ash-resource.html#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. ### [](dsl-ash-resource.html#nested-dsls-6)Nested DSLs - [action](dsl-ash-resource.html#actions-action) - argument - [create](dsl-ash-resource.html#actions-create) - change - validate - argument - metadata - [read](dsl-ash-resource.html#actions-read) - argument - prepare - pagination - metadata - filter - [update](dsl-ash-resource.html#actions-update) - change - validate - metadata - argument - [destroy](dsl-ash-resource.html#actions-destroy) - change - validate - metadata - argument ### [](dsl-ash-resource.html#examples-16)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 ``` ### [](dsl-ash-resource.html#options-5)Options NameTypeDefaultDocs[`defaults`](dsl-ash-resource.html#actions-defaults)`list(:create | :read | :update | :destroy | {atom, atom | list(atom)})`Creates a simple action of each specified type, with the same name as the type. These will be `primary?` unless one already exists for that type. Embedded resources, however, have a default of all resource types.[`default_accept`](dsl-ash-resource.html#actions-default_accept)`list(atom) | :*`A default value for the `accept` option for each action. Use `:*` to accept all public attributes. ### [](dsl-ash-resource.html#actions-action)actions.action ``` action name, returns \\ nil ``` Declares a generic action. A combination of arguments, a return type and a run function. For calling this action, see the [`Ash.Domain`](Ash.Domain.html) documentation. ### [](dsl-ash-resource.html#nested-dsls-7)Nested DSLs - [argument](dsl-ash-resource.html#actions-action-argument) ### [](dsl-ash-resource.html#examples-17)Examples ``` action :top_user_emails, {:array, :string} do argument :limit, :integer, default: 10, allow_nil?: false run fn input, context -> with {:ok, top_users} <- top_users(input.arguments.limit) do {:ok, Enum.map(top_users, &(&1.email))} end end end ``` ### [](dsl-ash-resource.html#arguments-14)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-action-name)`atom`The name of the action[`returns`](dsl-ash-resource.html#actions-action-returns)`module`The return type of the action. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-6)Options NameTypeDefaultDocs[`constraints`](dsl-ash-resource.html#actions-action-constraints)`keyword`Constraints for the return type. See [`Ash.Type`](Ash.Type.html) for more.[`allow_nil?`](dsl-ash-resource.html#actions-action-allow_nil?)`boolean``false`Whether or not the action can return nil. Unlike attributes &amp; arguments, this defaults to `false`.[`run`](dsl-ash-resource.html#actions-action-run)`(any, any -> any) | module | module`[`primary?`](dsl-ash-resource.html#actions-action-primary?)`boolean``false`Whether or not this action should be used when no action is specified by the caller.[`description`](dsl-ash-resource.html#actions-action-description)`String.t`An optional description for the action[`transaction?`](dsl-ash-resource.html#actions-action-transaction?)`boolean`Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default to `true`.[`touches_resources`](dsl-ash-resource.html#actions-action-touches_resources)`list(atom)`A list of resources that the action may touch, used when building transactions.[`skip_unknown_inputs`](dsl-ash-resource.html#actions-action-skip_unknown_inputs)`atom | String.t | list(atom | String.t)``[]`A list of unknown fields to skip, or `:*` to skip all unknown fields. ### [](dsl-ash-resource.html#actions-action-argument)actions.action.argument ``` argument name, type ``` Declares an argument on the action ### [](dsl-ash-resource.html#examples-18)Examples ``` argument :password_confirmation, :string ``` ### [](dsl-ash-resource.html#arguments-15)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-action-argument-name)`atom`The name of the argument[`type`](dsl-ash-resource.html#actions-action-argument-type)`module`The type of the argument. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-7)Options NameTypeDefaultDocs[`description`](dsl-ash-resource.html#actions-action-argument-description)`String.t`An optional description for the argument.[`constraints`](dsl-ash-resource.html#actions-action-argument-constraints)`keyword``[]`Constraints to provide to the type when casting the value. For more information, see [`Ash.Type`](Ash.Type.html).[`allow_nil?`](dsl-ash-resource.html#actions-action-argument-allow_nil?)`boolean``true`Whether or not the argument value may be nil (or may be not provided). If nil value is given error is raised.[`public?`](dsl-ash-resource.html#actions-action-argument-public?)`boolean``true`Whether or not the argument should appear in public interfaces[`sensitive?`](dsl-ash-resource.html#actions-action-argument-sensitive?)`boolean``false`Whether or not the argument value contains sensitive information, like PII(Personally Identifiable Information). See the [security guide](sensitive-data.html) for more.[`default`](dsl-ash-resource.html#actions-action-argument-default)`any`The default value for the argument to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-14)Introspection Target: [`Ash.Resource.Actions.Argument`](Ash.Resource.Actions.Argument.html) ### [](dsl-ash-resource.html#introspection-15)Introspection Target: [`Ash.Resource.Actions.Action`](Ash.Resource.Actions.Action.html) ### [](dsl-ash-resource.html#actions-create)actions.create ``` create name ``` Declares a `create` action. For calling this action, see the [`Ash.Domain`](Ash.Domain.html) documentation. ### [](dsl-ash-resource.html#nested-dsls-8)Nested DSLs - [change](dsl-ash-resource.html#actions-create-change) - [validate](dsl-ash-resource.html#actions-create-validate) - [argument](dsl-ash-resource.html#actions-create-argument) - [metadata](dsl-ash-resource.html#actions-create-metadata) ### [](dsl-ash-resource.html#examples-19)Examples ``` create :register do primary? true end ``` ### [](dsl-ash-resource.html#arguments-16)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-create-name)`atom`The name of the action ### [](dsl-ash-resource.html#options-8)Options NameTypeDefaultDocs[`manual`](dsl-ash-resource.html#actions-create-manual)`(any, any -> any) | module`Override the creation behavior. Accepts a module or module and opts, or a function that takes the changeset and context. See the [manual actions guide](manual-actions.html) for more.[`upsert?`](dsl-ash-resource.html#actions-create-upsert?)`boolean``false`Forces all uses of this action to be treated as an upsert.[`upsert_identity`](dsl-ash-resource.html#actions-create-upsert_identity)`atom`The identity to use for the upsert. Cannot be overriden by the caller. Ignored if `upsert?` is not set to `true`.[`upsert_fields`](dsl-ash-resource.html#actions-create-upsert_fields)`:replace_all | {:replace, atom | list(atom)} | {:replace_all_except, atom | list(atom)} | atom | list(atom)`The fields to overwrite in the case of an upsert. If not provided, all fields except for fields set by defaults will be overwritten.[`upsert_condition`](dsl-ash-resource.html#actions-create-upsert_condition)`any`An expression to check if the record should be updated when there's a conflict.[`return_skipped_upsert?`](dsl-ash-resource.html#actions-create-return_skipped_upsert?)`boolean`Returns the record that would have been upserted against but was skipped due to a filter or no fields being changed. How this works depends on the data layer. Keep in mind that read policies *are not applied* to the read of the record in question.[`primary?`](dsl-ash-resource.html#actions-create-primary?)`boolean``false`Whether or not this action should be used when no action is specified by the caller.[`description`](dsl-ash-resource.html#actions-create-description)`String.t`An optional description for the action[`transaction?`](dsl-ash-resource.html#actions-create-transaction?)`boolean`Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default to `true`.[`touches_resources`](dsl-ash-resource.html#actions-create-touches_resources)`list(atom)`A list of resources that the action may touch, used when building transactions.[`skip_unknown_inputs`](dsl-ash-resource.html#actions-create-skip_unknown_inputs)`atom | String.t | list(atom | String.t)``[]`A list of unknown fields to skip, or `:*` to skip all unknown fields.[`accept`](dsl-ash-resource.html#actions-create-accept)`atom | list(atom) | :*`The list of attributes to accept. Use `:*` to accept all public attributes.[`action_select`](dsl-ash-resource.html#actions-create-action_select)`list(atom)`A list of attributes that the action requires to do its work. Defaults to all attributes except those with `select_by_default? false`. On actions with no changes/notifiers, it defaults to the externally selected attributes. Keep in mind that action\_select is applied *before* notifiers.[`require_attributes`](dsl-ash-resource.html#actions-create-require_attributes)`list(atom)`A list of attributes that would normally `allow_nil?`, to require for this action. No need to include attributes that already do not allow nil?[`allow_nil_input`](dsl-ash-resource.html#actions-create-allow_nil_input)`list(atom)`A list of attributes that would normally be required, but should not be for this action. They will still be validated just before the data layer step.[`delay_global_validations?`](dsl-ash-resource.html#actions-create-delay_global_validations?)`boolean``false`If true, global validations will be done in a `before_action` hook, regardless of their configuration on the resource.[`skip_global_validations?`](dsl-ash-resource.html#actions-create-skip_global_validations?)`boolean``false`If true, global validations will be skipped. Useful for manual actions.[`error_handler`](dsl-ash-resource.html#actions-create-error_handler)`mfa`Sets the error handler on the changeset. See [`Ash.Changeset.handle_errors/2`](Ash.Changeset.html#handle_errors/2) for more[`notifiers`](dsl-ash-resource.html#actions-create-notifiers)`list(module)`Notifiers that will be called specifically for this action.[`manual?`](dsl-ash-resource.html#actions-create-manual?)`boolean`Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](manual-actions.html) for more. ### [](dsl-ash-resource.html#actions-create-change)actions.create.change ``` change change ``` A change to be applied to the changeset. See [`Ash.Resource.Change`](Ash.Resource.Change.html) for more. ### [](dsl-ash-resource.html#examples-20)Examples ``` change relate_actor(:reporter) ``` ``` change {MyCustomChange, :foo} ``` ### [](dsl-ash-resource.html#arguments-17)Arguments NameTypeDefaultDocs[`change`](dsl-ash-resource.html#actions-create-change-change)`(any, any -> any) | module`The module and options for a change. Also accepts a function that takes the changeset and the context. See [`Ash.Resource.Change.Builtins`](Ash.Resource.Change.Builtins.html) for builtin changes. ### [](dsl-ash-resource.html#options-9)Options NameTypeDefaultDocs[`only_when_valid?`](dsl-ash-resource.html#actions-create-change-only_when_valid?)`boolean``false`If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here.[`description`](dsl-ash-resource.html#actions-create-change-description)`String.t`An optional description for the change[`where`](dsl-ash-resource.html#actions-create-change-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this change to apply. These validations failing will result in this change being ignored.[`always_atomic?`](dsl-ash-resource.html#actions-create-change-always_atomic?)`boolean``false`By default, changes are only run atomically if all changes will be run atomically or if there is no `change/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-16)Introspection Target: [`Ash.Resource.Change`](Ash.Resource.Change.html) ### [](dsl-ash-resource.html#actions-create-validate)actions.create.validate ``` validate validation ``` Declares a validation to be applied to the changeset. See [`Ash.Resource.Validation.Builtins`](Ash.Resource.Validation.Builtins.html) or [`Ash.Resource.Validation`](Ash.Resource.Validation.html) for more. ### [](dsl-ash-resource.html#examples-21)Examples ``` validate changing(:email) ``` ### [](dsl-ash-resource.html#arguments-18)Arguments NameTypeDefaultDocs[`validation`](dsl-ash-resource.html#actions-create-validate-validation)`(any, any -> any) | module`The module (or module and opts) that implements the [`Ash.Resource.Validation`](Ash.Resource.Validation.html) behaviour. Also accepts a function that receives the changeset and its context. ### [](dsl-ash-resource.html#options-10)Options NameTypeDefaultDocs[`where`](dsl-ash-resource.html#actions-create-validate-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this validation to apply. Any of these validations failing will result in this validation being ignored.[`only_when_valid?`](dsl-ash-resource.html#actions-create-validate-only_when_valid?)`boolean``false`If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data.[`message`](dsl-ash-resource.html#actions-create-validate-message)`String.t`If provided, overrides any message set by the validation error[`description`](dsl-ash-resource.html#actions-create-validate-description)`String.t`An optional description for the validation[`before_action?`](dsl-ash-resource.html#actions-create-validate-before_action?)`boolean``false`If set to `true`, the validation will be run in a before\_action hook[`always_atomic?`](dsl-ash-resource.html#actions-create-validate-always_atomic?)`boolean``false`By default, validations are only run atomically if all changes will be run atomically or if there is no `validate/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-17)Introspection Target: [`Ash.Resource.Validation`](Ash.Resource.Validation.html) ### [](dsl-ash-resource.html#actions-create-argument)actions.create.argument ``` argument name, type ``` Declares an argument on the action ### [](dsl-ash-resource.html#examples-22)Examples ``` argument :password_confirmation, :string ``` ### [](dsl-ash-resource.html#arguments-19)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-create-argument-name)`atom`The name of the argument[`type`](dsl-ash-resource.html#actions-create-argument-type)`module`The type of the argument. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-11)Options NameTypeDefaultDocs[`description`](dsl-ash-resource.html#actions-create-argument-description)`String.t`An optional description for the argument.[`constraints`](dsl-ash-resource.html#actions-create-argument-constraints)`keyword``[]`Constraints to provide to the type when casting the value. For more information, see [`Ash.Type`](Ash.Type.html).[`allow_nil?`](dsl-ash-resource.html#actions-create-argument-allow_nil?)`boolean``true`Whether or not the argument value may be nil (or may be not provided). If nil value is given error is raised.[`public?`](dsl-ash-resource.html#actions-create-argument-public?)`boolean``true`Whether or not the argument should appear in public interfaces[`sensitive?`](dsl-ash-resource.html#actions-create-argument-sensitive?)`boolean``false`Whether or not the argument value contains sensitive information, like PII(Personally Identifiable Information). See the [security guide](sensitive-data.html) for more.[`default`](dsl-ash-resource.html#actions-create-argument-default)`any`The default value for the argument to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-18)Introspection Target: [`Ash.Resource.Actions.Argument`](Ash.Resource.Actions.Argument.html) ### [](dsl-ash-resource.html#actions-create-metadata)actions.create.metadata ``` metadata name, type ``` A special kind of attribute that is only added to specific actions. Nothing sets this value, it must be set in a custom change after\_action hook via [`Ash.Resource.put_metadata/3`](Ash.Resource.html#put_metadata/3). ### [](dsl-ash-resource.html#examples-23)Examples ``` metadata :api_token, :string, allow_nil?: false ``` ``` metadata :operation_id, :string, allow_nil?: false ``` ### [](dsl-ash-resource.html#arguments-20)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-create-metadata-name)`atom`The name of the metadata[`type`](dsl-ash-resource.html#actions-create-metadata-type)`any`The type of the metadata. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-12)Options NameTypeDefaultDocs[`constraints`](dsl-ash-resource.html#actions-create-metadata-constraints)`keyword``[]`Type constraints on the metadata[`description`](dsl-ash-resource.html#actions-create-metadata-description)`String.t`An optional description for the metadata.[`allow_nil?`](dsl-ash-resource.html#actions-create-metadata-allow_nil?)`boolean``true`Whether or not the metadata may return `nil`[`default`](dsl-ash-resource.html#actions-create-metadata-default)`any`The default value for the metadata to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-19)Introspection Target: [`Ash.Resource.Actions.Metadata`](Ash.Resource.Actions.Metadata.html) ### [](dsl-ash-resource.html#introspection-20)Introspection Target: [`Ash.Resource.Actions.Create`](Ash.Resource.Actions.Create.html) ### [](dsl-ash-resource.html#actions-read)actions.read ``` read name ``` Declares a `read` action. For calling this action, see the [`Ash.Domain`](Ash.Domain.html) documentation. ### [](dsl-ash-resource.html#nested-dsls-9)Nested DSLs - [argument](dsl-ash-resource.html#actions-read-argument) - [prepare](dsl-ash-resource.html#actions-read-prepare) - [pagination](dsl-ash-resource.html#actions-read-pagination) - [metadata](dsl-ash-resource.html#actions-read-metadata) - [filter](dsl-ash-resource.html#actions-read-filter) ### [](dsl-ash-resource.html#examples-24)Examples ``` read :read_all do primary? true end ``` ### [](dsl-ash-resource.html#arguments-21)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-read-name)`atom`The name of the action ### [](dsl-ash-resource.html#options-13)Options NameTypeDefaultDocs[`manual`](dsl-ash-resource.html#actions-read-manual)`(any, any, any -> any) | module`Delegates running of the query to the provided module. Accepts a module or module and opts, or a function that takes the ash query, the data layer query, and context. See the [manual actions guide](manual-actions.html) for more.[`get?`](dsl-ash-resource.html#actions-read-get?)`boolean``false`Expresses that this action innately only returns a single result. Used by extensions to validate and/or modify behavior. Causes code interfaces to return a single value instead of a list. See the [code interface guide](code-interfaces.html) for more.[`modify_query`](dsl-ash-resource.html#actions-read-modify_query)`mfa | (any, any -> any)`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}`.[`get_by`](dsl-ash-resource.html#actions-read-get_by)`atom | list(atom)`A helper to automatically generate a "get by X" action. Sets `get?` to true, add args for each of the specified fields, and adds a filter for each of the arguments.[`timeout`](dsl-ash-resource.html#actions-read-timeout)`pos_integer`The maximum amount of time, in milliseconds, that the action is allowed to run for. Ignored if the data layer doesn't support transactions *and* async is disabled.[`multitenancy`](dsl-ash-resource.html#actions-read-multitenancy)`:enforce | :allow_global | :bypass``:enforce`This setting defines how this action handles multitenancy. `:enforce` requires a tenant to be set (the default behavior), `:allow_global` allows using this action both with and without a tenant, `:bypass` completely ignores the tenant even if it's set. This is useful to change the behaviour of selected read action without the need of marking the whole resource with `global? true`.[`primary?`](dsl-ash-resource.html#actions-read-primary?)`boolean``false`Whether or not this action should be used when no action is specified by the caller.[`description`](dsl-ash-resource.html#actions-read-description)`String.t`An optional description for the action[`transaction?`](dsl-ash-resource.html#actions-read-transaction?)`boolean`Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default to `true`.[`touches_resources`](dsl-ash-resource.html#actions-read-touches_resources)`list(atom)`A list of resources that the action may touch, used when building transactions.[`skip_unknown_inputs`](dsl-ash-resource.html#actions-read-skip_unknown_inputs)`atom | String.t | list(atom | String.t)``[]`A list of unknown fields to skip, or `:*` to skip all unknown fields. ### [](dsl-ash-resource.html#actions-read-argument)actions.read.argument ``` argument name, type ``` Declares an argument on the action ### [](dsl-ash-resource.html#examples-25)Examples ``` argument :password_confirmation, :string ``` ### [](dsl-ash-resource.html#arguments-22)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-read-argument-name)`atom`The name of the argument[`type`](dsl-ash-resource.html#actions-read-argument-type)`module`The type of the argument. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-14)Options NameTypeDefaultDocs[`description`](dsl-ash-resource.html#actions-read-argument-description)`String.t`An optional description for the argument.[`constraints`](dsl-ash-resource.html#actions-read-argument-constraints)`keyword``[]`Constraints to provide to the type when casting the value. For more information, see [`Ash.Type`](Ash.Type.html).[`allow_nil?`](dsl-ash-resource.html#actions-read-argument-allow_nil?)`boolean``true`Whether or not the argument value may be nil (or may be not provided). If nil value is given error is raised.[`public?`](dsl-ash-resource.html#actions-read-argument-public?)`boolean``true`Whether or not the argument should appear in public interfaces[`sensitive?`](dsl-ash-resource.html#actions-read-argument-sensitive?)`boolean``false`Whether or not the argument value contains sensitive information, like PII(Personally Identifiable Information). See the [security guide](sensitive-data.html) for more.[`default`](dsl-ash-resource.html#actions-read-argument-default)`any`The default value for the argument to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-21)Introspection Target: [`Ash.Resource.Actions.Argument`](Ash.Resource.Actions.Argument.html) ### [](dsl-ash-resource.html#actions-read-prepare)actions.read.prepare ``` prepare preparation ``` Declares a preparation, which can be used to prepare a query for a read action. ### [](dsl-ash-resource.html#examples-26)Examples ``` prepare build(sort: [:foo, :bar]) ``` ### [](dsl-ash-resource.html#arguments-23)Arguments NameTypeDefaultDocs[`preparation`](dsl-ash-resource.html#actions-read-prepare-preparation)`(any, any -> any) | module`The module and options for a preparation. Also accepts functions take the query and the context. ### [](dsl-ash-resource.html#introspection-22)Introspection Target: [`Ash.Resource.Preparation`](Ash.Resource.Preparation.html) ### [](dsl-ash-resource.html#actions-read-pagination)actions.read.pagination Adds pagination options to a resource ### [](dsl-ash-resource.html#options-15)Options NameTypeDefaultDocs[`keyset?`](dsl-ash-resource.html#actions-read-pagination-keyset?)`boolean``false`Whether or not keyset based pagination is supported[`offset?`](dsl-ash-resource.html#actions-read-pagination-offset?)`boolean``false`Whether or not offset based pagination is supported[`default_limit`](dsl-ash-resource.html#actions-read-pagination-default_limit)`pos_integer`The default page size to apply, if one is not supplied[`countable`](dsl-ash-resource.html#actions-read-pagination-countable)`true | false | :by_default``true`Whether not a returned page will have a full count of all records. Use `:by_default` to do it automatically.[`max_page_size`](dsl-ash-resource.html#actions-read-pagination-max_page_size)`pos_integer``250`The maximum amount of records that can be requested in a single page[`required?`](dsl-ash-resource.html#actions-read-pagination-required?)`boolean``true`Whether or not pagination can be disabled (by passing `page: false` to `Ash.Api.read!/2`, or by having `required?: false, default_limit: nil` set). Only relevant if some pagination configuration is supplied. ### [](dsl-ash-resource.html#introspection-23)Introspection Target: [`Ash.Resource.Actions.Read.Pagination`](Ash.Resource.Actions.Read.Pagination.html) ### [](dsl-ash-resource.html#actions-read-metadata)actions.read.metadata ``` metadata name, type ``` A special kind of attribute that is only added to specific actions. Nothing sets this value, it must be set in a custom change after\_action hook via [`Ash.Resource.put_metadata/3`](Ash.Resource.html#put_metadata/3). ### [](dsl-ash-resource.html#examples-27)Examples ``` metadata :api_token, :string, allow_nil?: false ``` ``` metadata :operation_id, :string, allow_nil?: false ``` ### [](dsl-ash-resource.html#arguments-24)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-read-metadata-name)`atom`The name of the metadata[`type`](dsl-ash-resource.html#actions-read-metadata-type)`any`The type of the metadata. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-16)Options NameTypeDefaultDocs[`constraints`](dsl-ash-resource.html#actions-read-metadata-constraints)`keyword``[]`Type constraints on the metadata[`description`](dsl-ash-resource.html#actions-read-metadata-description)`String.t`An optional description for the metadata.[`allow_nil?`](dsl-ash-resource.html#actions-read-metadata-allow_nil?)`boolean``true`Whether or not the metadata may return `nil`[`default`](dsl-ash-resource.html#actions-read-metadata-default)`any`The default value for the metadata to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-24)Introspection Target: [`Ash.Resource.Actions.Metadata`](Ash.Resource.Actions.Metadata.html) ### [](dsl-ash-resource.html#actions-read-filter)actions.read.filter ``` filter filter ``` Applies a filter. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#examples-28)Examples ``` filter expr(first_name == "fred") filter expr(last_name == "weasley" and magician == true) ``` ### [](dsl-ash-resource.html#arguments-25)Arguments NameTypeDefaultDocs[`filter`](dsl-ash-resource.html#actions-read-filter-filter)`any`The filter to apply. Can use [`^arg/1`](../elixir/Kernel.SpecialForms.html#%5E/1), [`^context/1`](../elixir/Kernel.SpecialForms.html#%5E/1) and [`^actor/1`](../elixir/Kernel.SpecialForms.html#%5E/1) templates. Multiple filters are combined with *and*. ### [](dsl-ash-resource.html#introspection-25)Introspection Target: [`Ash.Resource.Dsl.Filter`](Ash.Resource.Dsl.Filter.html) ### [](dsl-ash-resource.html#introspection-26)Introspection Target: [`Ash.Resource.Actions.Read`](Ash.Resource.Actions.Read.html) ### [](dsl-ash-resource.html#actions-update)actions.update ``` update name ``` Declares a `update` action. For calling this action, see the [`Ash.Domain`](Ash.Domain.html) documentation. ### [](dsl-ash-resource.html#nested-dsls-10)Nested DSLs - [change](dsl-ash-resource.html#actions-update-change) - [validate](dsl-ash-resource.html#actions-update-validate) - [metadata](dsl-ash-resource.html#actions-update-metadata) - [argument](dsl-ash-resource.html#actions-update-argument) ### [](dsl-ash-resource.html#examples-29)Examples ``` update :flag_for_review, primary?: true ``` ### [](dsl-ash-resource.html#arguments-26)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-update-name)`atom`The name of the action ### [](dsl-ash-resource.html#options-17)Options NameTypeDefaultDocs[`manual`](dsl-ash-resource.html#actions-update-manual)`(any, any -> any) | module`Override the update behavior. Accepts a module or module and opts, or a function that takes the changeset and context. See the [manual actions guide](manual-actions.html) for more.[`require_atomic?`](dsl-ash-resource.html#actions-update-require_atomic?)`boolean``true`Require that the update be atomic. This means that all changes and validations implement the `atomic` callback. See the guide on atomic updates for more.[`atomic_upgrade?`](dsl-ash-resource.html#actions-update-atomic_upgrade?)`boolean``false`If set to `true`, atomic upgrades will be performed. Ignored if `required_atomic?` is `true`. See the update actions guide for more.[`atomic_upgrade_with`](dsl-ash-resource.html#actions-update-atomic_upgrade_with)`atom | nil`Configure the read action used when performing atomic upgrades. Defaults to the primary read action.[`primary?`](dsl-ash-resource.html#actions-update-primary?)`boolean``false`Whether or not this action should be used when no action is specified by the caller.[`description`](dsl-ash-resource.html#actions-update-description)`String.t`An optional description for the action[`transaction?`](dsl-ash-resource.html#actions-update-transaction?)`boolean`Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default to `true`.[`touches_resources`](dsl-ash-resource.html#actions-update-touches_resources)`list(atom)`A list of resources that the action may touch, used when building transactions.[`skip_unknown_inputs`](dsl-ash-resource.html#actions-update-skip_unknown_inputs)`atom | String.t | list(atom | String.t)``[]`A list of unknown fields to skip, or `:*` to skip all unknown fields.[`accept`](dsl-ash-resource.html#actions-update-accept)`atom | list(atom) | :*`The list of attributes to accept. Use `:*` to accept all public attributes.[`action_select`](dsl-ash-resource.html#actions-update-action_select)`list(atom)`A list of attributes that the action requires to do its work. Defaults to all attributes except those with `select_by_default? false`. On actions with no changes/notifiers, it defaults to the externally selected attributes. Keep in mind that action\_select is applied *before* notifiers.[`require_attributes`](dsl-ash-resource.html#actions-update-require_attributes)`list(atom)`A list of attributes that would normally `allow_nil?`, to require for this action. No need to include attributes that already do not allow nil?[`allow_nil_input`](dsl-ash-resource.html#actions-update-allow_nil_input)`list(atom)`A list of attributes that would normally be required, but should not be for this action. They will still be validated just before the data layer step.[`delay_global_validations?`](dsl-ash-resource.html#actions-update-delay_global_validations?)`boolean``false`If true, global validations will be done in a `before_action` hook, regardless of their configuration on the resource.[`skip_global_validations?`](dsl-ash-resource.html#actions-update-skip_global_validations?)`boolean``false`If true, global validations will be skipped. Useful for manual actions.[`error_handler`](dsl-ash-resource.html#actions-update-error_handler)`mfa`Sets the error handler on the changeset. See [`Ash.Changeset.handle_errors/2`](Ash.Changeset.html#handle_errors/2) for more[`notifiers`](dsl-ash-resource.html#actions-update-notifiers)`list(module)`Notifiers that will be called specifically for this action.[`manual?`](dsl-ash-resource.html#actions-update-manual?)`boolean`Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](manual-actions.html) for more. ### [](dsl-ash-resource.html#actions-update-change)actions.update.change ``` change change ``` A change to be applied to the changeset. See [`Ash.Resource.Change`](Ash.Resource.Change.html) for more. ### [](dsl-ash-resource.html#examples-30)Examples ``` change relate_actor(:reporter) ``` ``` change {MyCustomChange, :foo} ``` ### [](dsl-ash-resource.html#arguments-27)Arguments NameTypeDefaultDocs[`change`](dsl-ash-resource.html#actions-update-change-change)`(any, any -> any) | module`The module and options for a change. Also accepts a function that takes the changeset and the context. See [`Ash.Resource.Change.Builtins`](Ash.Resource.Change.Builtins.html) for builtin changes. ### [](dsl-ash-resource.html#options-18)Options NameTypeDefaultDocs[`only_when_valid?`](dsl-ash-resource.html#actions-update-change-only_when_valid?)`boolean``false`If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here.[`description`](dsl-ash-resource.html#actions-update-change-description)`String.t`An optional description for the change[`where`](dsl-ash-resource.html#actions-update-change-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this change to apply. These validations failing will result in this change being ignored.[`always_atomic?`](dsl-ash-resource.html#actions-update-change-always_atomic?)`boolean``false`By default, changes are only run atomically if all changes will be run atomically or if there is no `change/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-27)Introspection Target: [`Ash.Resource.Change`](Ash.Resource.Change.html) ### [](dsl-ash-resource.html#actions-update-validate)actions.update.validate ``` validate validation ``` Declares a validation to be applied to the changeset. See [`Ash.Resource.Validation.Builtins`](Ash.Resource.Validation.Builtins.html) or [`Ash.Resource.Validation`](Ash.Resource.Validation.html) for more. ### [](dsl-ash-resource.html#examples-31)Examples ``` validate changing(:email) ``` ### [](dsl-ash-resource.html#arguments-28)Arguments NameTypeDefaultDocs[`validation`](dsl-ash-resource.html#actions-update-validate-validation)`(any, any -> any) | module`The module (or module and opts) that implements the [`Ash.Resource.Validation`](Ash.Resource.Validation.html) behaviour. Also accepts a function that receives the changeset and its context. ### [](dsl-ash-resource.html#options-19)Options NameTypeDefaultDocs[`where`](dsl-ash-resource.html#actions-update-validate-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this validation to apply. Any of these validations failing will result in this validation being ignored.[`only_when_valid?`](dsl-ash-resource.html#actions-update-validate-only_when_valid?)`boolean``false`If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data.[`message`](dsl-ash-resource.html#actions-update-validate-message)`String.t`If provided, overrides any message set by the validation error[`description`](dsl-ash-resource.html#actions-update-validate-description)`String.t`An optional description for the validation[`before_action?`](dsl-ash-resource.html#actions-update-validate-before_action?)`boolean``false`If set to `true`, the validation will be run in a before\_action hook[`always_atomic?`](dsl-ash-resource.html#actions-update-validate-always_atomic?)`boolean``false`By default, validations are only run atomically if all changes will be run atomically or if there is no `validate/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-28)Introspection Target: [`Ash.Resource.Validation`](Ash.Resource.Validation.html) ### [](dsl-ash-resource.html#actions-update-metadata)actions.update.metadata ``` metadata name, type ``` A special kind of attribute that is only added to specific actions. Nothing sets this value, it must be set in a custom change after\_action hook via [`Ash.Resource.put_metadata/3`](Ash.Resource.html#put_metadata/3). ### [](dsl-ash-resource.html#examples-32)Examples ``` metadata :api_token, :string, allow_nil?: false ``` ``` metadata :operation_id, :string, allow_nil?: false ``` ### [](dsl-ash-resource.html#arguments-29)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-update-metadata-name)`atom`The name of the metadata[`type`](dsl-ash-resource.html#actions-update-metadata-type)`any`The type of the metadata. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-20)Options NameTypeDefaultDocs[`constraints`](dsl-ash-resource.html#actions-update-metadata-constraints)`keyword``[]`Type constraints on the metadata[`description`](dsl-ash-resource.html#actions-update-metadata-description)`String.t`An optional description for the metadata.[`allow_nil?`](dsl-ash-resource.html#actions-update-metadata-allow_nil?)`boolean``true`Whether or not the metadata may return `nil`[`default`](dsl-ash-resource.html#actions-update-metadata-default)`any`The default value for the metadata to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-29)Introspection Target: [`Ash.Resource.Actions.Metadata`](Ash.Resource.Actions.Metadata.html) ### [](dsl-ash-resource.html#actions-update-argument)actions.update.argument ``` argument name, type ``` Declares an argument on the action ### [](dsl-ash-resource.html#examples-33)Examples ``` argument :password_confirmation, :string ``` ### [](dsl-ash-resource.html#arguments-30)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-update-argument-name)`atom`The name of the argument[`type`](dsl-ash-resource.html#actions-update-argument-type)`module`The type of the argument. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-21)Options NameTypeDefaultDocs[`description`](dsl-ash-resource.html#actions-update-argument-description)`String.t`An optional description for the argument.[`constraints`](dsl-ash-resource.html#actions-update-argument-constraints)`keyword``[]`Constraints to provide to the type when casting the value. For more information, see [`Ash.Type`](Ash.Type.html).[`allow_nil?`](dsl-ash-resource.html#actions-update-argument-allow_nil?)`boolean``true`Whether or not the argument value may be nil (or may be not provided). If nil value is given error is raised.[`public?`](dsl-ash-resource.html#actions-update-argument-public?)`boolean``true`Whether or not the argument should appear in public interfaces[`sensitive?`](dsl-ash-resource.html#actions-update-argument-sensitive?)`boolean``false`Whether or not the argument value contains sensitive information, like PII(Personally Identifiable Information). See the [security guide](sensitive-data.html) for more.[`default`](dsl-ash-resource.html#actions-update-argument-default)`any`The default value for the argument to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-30)Introspection Target: [`Ash.Resource.Actions.Argument`](Ash.Resource.Actions.Argument.html) ### [](dsl-ash-resource.html#introspection-31)Introspection Target: [`Ash.Resource.Actions.Update`](Ash.Resource.Actions.Update.html) ### [](dsl-ash-resource.html#actions-destroy)actions.destroy ``` destroy name ``` Declares a `destroy` action. For calling this action, see the [`Ash.Domain`](Ash.Domain.html) documentation. ### [](dsl-ash-resource.html#nested-dsls-11)Nested DSLs - [change](dsl-ash-resource.html#actions-destroy-change) - [validate](dsl-ash-resource.html#actions-destroy-validate) - [metadata](dsl-ash-resource.html#actions-destroy-metadata) - [argument](dsl-ash-resource.html#actions-destroy-argument) ### [](dsl-ash-resource.html#examples-34)Examples ``` destroy :destroy do primary? true end ``` ### [](dsl-ash-resource.html#arguments-31)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-destroy-name)`atom`The name of the action ### [](dsl-ash-resource.html#options-22)Options NameTypeDefaultDocs[`soft?`](dsl-ash-resource.html#actions-destroy-soft?)`boolean``false`If specified, the destroy action behaves as an update internally[`manual`](dsl-ash-resource.html#actions-destroy-manual)`(any, any -> any) | module`Override the update behavior. Accepts a module or module and opts, or a function that takes the changeset and context. See the [manual actions guide](manual-actions.html) for more.[`require_atomic?`](dsl-ash-resource.html#actions-destroy-require_atomic?)`boolean``true`Require that the update be atomic. Only relevant if `soft?` is set to `true`. This means that all changes and validations implement the `atomic` callback. See the guide on atomic updates for more.[`atomic_upgrade?`](dsl-ash-resource.html#actions-destroy-atomic_upgrade?)`boolean``false`If set to `true`, atomic upgrades will be performed. See the update actions guide for more.[`atomic_upgrade_with`](dsl-ash-resource.html#actions-destroy-atomic_upgrade_with)`atom | nil`Configure the read action used when performing atomic upgrades. Defaults to the primary read action.[`primary?`](dsl-ash-resource.html#actions-destroy-primary?)`boolean``false`Whether or not this action should be used when no action is specified by the caller.[`description`](dsl-ash-resource.html#actions-destroy-description)`String.t`An optional description for the action[`transaction?`](dsl-ash-resource.html#actions-destroy-transaction?)`boolean`Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default to `true`.[`touches_resources`](dsl-ash-resource.html#actions-destroy-touches_resources)`list(atom)`A list of resources that the action may touch, used when building transactions.[`skip_unknown_inputs`](dsl-ash-resource.html#actions-destroy-skip_unknown_inputs)`atom | String.t | list(atom | String.t)``[]`A list of unknown fields to skip, or `:*` to skip all unknown fields.[`accept`](dsl-ash-resource.html#actions-destroy-accept)`atom | list(atom) | :*`The list of attributes to accept. Use `:*` to accept all public attributes.[`action_select`](dsl-ash-resource.html#actions-destroy-action_select)`list(atom)`A list of attributes that the action requires to do its work. Defaults to all attributes except those with `select_by_default? false`. On actions with no changes/notifiers, it defaults to the externally selected attributes. Keep in mind that action\_select is applied *before* notifiers.[`require_attributes`](dsl-ash-resource.html#actions-destroy-require_attributes)`list(atom)`A list of attributes that would normally `allow_nil?`, to require for this action. No need to include attributes that already do not allow nil?[`allow_nil_input`](dsl-ash-resource.html#actions-destroy-allow_nil_input)`list(atom)`A list of attributes that would normally be required, but should not be for this action. They will still be validated just before the data layer step.[`delay_global_validations?`](dsl-ash-resource.html#actions-destroy-delay_global_validations?)`boolean``false`If true, global validations will be done in a `before_action` hook, regardless of their configuration on the resource.[`skip_global_validations?`](dsl-ash-resource.html#actions-destroy-skip_global_validations?)`boolean``false`If true, global validations will be skipped. Useful for manual actions.[`error_handler`](dsl-ash-resource.html#actions-destroy-error_handler)`mfa`Sets the error handler on the changeset. See [`Ash.Changeset.handle_errors/2`](Ash.Changeset.html#handle_errors/2) for more[`notifiers`](dsl-ash-resource.html#actions-destroy-notifiers)`list(module)`Notifiers that will be called specifically for this action.[`manual?`](dsl-ash-resource.html#actions-destroy-manual?)`boolean`Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](manual-actions.html) for more. ### [](dsl-ash-resource.html#actions-destroy-change)actions.destroy.change ``` change change ``` A change to be applied to the changeset. See [`Ash.Resource.Change`](Ash.Resource.Change.html) for more. ### [](dsl-ash-resource.html#examples-35)Examples ``` change relate_actor(:reporter) ``` ``` change {MyCustomChange, :foo} ``` ### [](dsl-ash-resource.html#arguments-32)Arguments NameTypeDefaultDocs[`change`](dsl-ash-resource.html#actions-destroy-change-change)`(any, any -> any) | module`The module and options for a change. Also accepts a function that takes the changeset and the context. See [`Ash.Resource.Change.Builtins`](Ash.Resource.Change.Builtins.html) for builtin changes. ### [](dsl-ash-resource.html#options-23)Options NameTypeDefaultDocs[`only_when_valid?`](dsl-ash-resource.html#actions-destroy-change-only_when_valid?)`boolean``false`If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here.[`description`](dsl-ash-resource.html#actions-destroy-change-description)`String.t`An optional description for the change[`where`](dsl-ash-resource.html#actions-destroy-change-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this change to apply. These validations failing will result in this change being ignored.[`always_atomic?`](dsl-ash-resource.html#actions-destroy-change-always_atomic?)`boolean``false`By default, changes are only run atomically if all changes will be run atomically or if there is no `change/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-32)Introspection Target: [`Ash.Resource.Change`](Ash.Resource.Change.html) ### [](dsl-ash-resource.html#actions-destroy-validate)actions.destroy.validate ``` validate validation ``` Declares a validation to be applied to the changeset. See [`Ash.Resource.Validation.Builtins`](Ash.Resource.Validation.Builtins.html) or [`Ash.Resource.Validation`](Ash.Resource.Validation.html) for more. ### [](dsl-ash-resource.html#examples-36)Examples ``` validate changing(:email) ``` ### [](dsl-ash-resource.html#arguments-33)Arguments NameTypeDefaultDocs[`validation`](dsl-ash-resource.html#actions-destroy-validate-validation)`(any, any -> any) | module`The module (or module and opts) that implements the [`Ash.Resource.Validation`](Ash.Resource.Validation.html) behaviour. Also accepts a function that receives the changeset and its context. ### [](dsl-ash-resource.html#options-24)Options NameTypeDefaultDocs[`where`](dsl-ash-resource.html#actions-destroy-validate-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this validation to apply. Any of these validations failing will result in this validation being ignored.[`only_when_valid?`](dsl-ash-resource.html#actions-destroy-validate-only_when_valid?)`boolean``false`If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data.[`message`](dsl-ash-resource.html#actions-destroy-validate-message)`String.t`If provided, overrides any message set by the validation error[`description`](dsl-ash-resource.html#actions-destroy-validate-description)`String.t`An optional description for the validation[`before_action?`](dsl-ash-resource.html#actions-destroy-validate-before_action?)`boolean``false`If set to `true`, the validation will be run in a before\_action hook[`always_atomic?`](dsl-ash-resource.html#actions-destroy-validate-always_atomic?)`boolean``false`By default, validations are only run atomically if all changes will be run atomically or if there is no `validate/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-33)Introspection Target: [`Ash.Resource.Validation`](Ash.Resource.Validation.html) ### [](dsl-ash-resource.html#actions-destroy-metadata)actions.destroy.metadata ``` metadata name, type ``` A special kind of attribute that is only added to specific actions. Nothing sets this value, it must be set in a custom change after\_action hook via [`Ash.Resource.put_metadata/3`](Ash.Resource.html#put_metadata/3). ### [](dsl-ash-resource.html#examples-37)Examples ``` metadata :api_token, :string, allow_nil?: false ``` ``` metadata :operation_id, :string, allow_nil?: false ``` ### [](dsl-ash-resource.html#arguments-34)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-destroy-metadata-name)`atom`The name of the metadata[`type`](dsl-ash-resource.html#actions-destroy-metadata-type)`any`The type of the metadata. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-25)Options NameTypeDefaultDocs[`constraints`](dsl-ash-resource.html#actions-destroy-metadata-constraints)`keyword``[]`Type constraints on the metadata[`description`](dsl-ash-resource.html#actions-destroy-metadata-description)`String.t`An optional description for the metadata.[`allow_nil?`](dsl-ash-resource.html#actions-destroy-metadata-allow_nil?)`boolean``true`Whether or not the metadata may return `nil`[`default`](dsl-ash-resource.html#actions-destroy-metadata-default)`any`The default value for the metadata to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-34)Introspection Target: [`Ash.Resource.Actions.Metadata`](Ash.Resource.Actions.Metadata.html) ### [](dsl-ash-resource.html#actions-destroy-argument)actions.destroy.argument ``` argument name, type ``` Declares an argument on the action ### [](dsl-ash-resource.html#examples-38)Examples ``` argument :password_confirmation, :string ``` ### [](dsl-ash-resource.html#arguments-35)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#actions-destroy-argument-name)`atom`The name of the argument[`type`](dsl-ash-resource.html#actions-destroy-argument-type)`module`The type of the argument. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-26)Options NameTypeDefaultDocs[`description`](dsl-ash-resource.html#actions-destroy-argument-description)`String.t`An optional description for the argument.[`constraints`](dsl-ash-resource.html#actions-destroy-argument-constraints)`keyword``[]`Constraints to provide to the type when casting the value. For more information, see [`Ash.Type`](Ash.Type.html).[`allow_nil?`](dsl-ash-resource.html#actions-destroy-argument-allow_nil?)`boolean``true`Whether or not the argument value may be nil (or may be not provided). If nil value is given error is raised.[`public?`](dsl-ash-resource.html#actions-destroy-argument-public?)`boolean``true`Whether or not the argument should appear in public interfaces[`sensitive?`](dsl-ash-resource.html#actions-destroy-argument-sensitive?)`boolean``false`Whether or not the argument value contains sensitive information, like PII(Personally Identifiable Information). See the [security guide](sensitive-data.html) for more.[`default`](dsl-ash-resource.html#actions-destroy-argument-default)`any`The default value for the argument to take. It can be a zero argument function e.g `&MyMod.my_fun/0` or a value ### [](dsl-ash-resource.html#introspection-35)Introspection Target: [`Ash.Resource.Actions.Argument`](Ash.Resource.Actions.Argument.html) ### [](dsl-ash-resource.html#introspection-36)Introspection Target: [`Ash.Resource.Actions.Destroy`](Ash.Resource.Actions.Destroy.html) ## [](dsl-ash-resource.html#code_interface)code\_interface Functions that will be defined on the resource. See the [code interface guide](code-interfaces.html) for more. ### [](dsl-ash-resource.html#nested-dsls-12)Nested DSLs - [define](dsl-ash-resource.html#code_interface-define) - [define\_calculation](dsl-ash-resource.html#code_interface-define_calculation) ### [](dsl-ash-resource.html#examples-39)Examples ``` code_interface do define :create_user, action: :create define :get_user_by_id, action: :get_by_id, args: [:id], get?: true end ``` ### [](dsl-ash-resource.html#options-27)Options NameTypeDefaultDocs[`domain`](dsl-ash-resource.html#code_interface-domain)`module``false`Use the provided Domain instead of the resources configured domain when calling actions.[`define?`](dsl-ash-resource.html#code_interface-define?)`boolean`Whether or not to define the code interface in the resource. ### [](dsl-ash-resource.html#code_interface-define)code\_interface.define ``` define name ``` Defines a function with the corresponding name and arguments. See the [code interface guide](code-interfaces.html) for more. ### [](dsl-ash-resource.html#examples-40)Examples ``` define :get_user_by_id, action: :get_by_id, args: [:id], get?: true ``` ### [](dsl-ash-resource.html#arguments-36)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#code_interface-define-name)`atom`The name of the function that will be defined ### [](dsl-ash-resource.html#options-28)Options NameTypeDefaultDocs[`action`](dsl-ash-resource.html#code_interface-define-action)`atom`The name of the action that will be called. Defaults to the same name as the function.[`args`](dsl-ash-resource.html#code_interface-define-args)`list(atom | {:optional, atom})`Map specific arguments to named inputs. Can provide any argument/attributes that the action allows.[`not_found_error?`](dsl-ash-resource.html#code_interface-define-not_found_error?)`boolean``true`If the action or interface is configured with `get?: true`, this determines whether or not an error is raised or `nil` is returned.[`require_reference?`](dsl-ash-resource.html#code_interface-define-require_reference?)`boolean``true`For update and destroy actions, require a resource or identifier to be passed in as the first argument. Not relevant for other action types.[`get?`](dsl-ash-resource.html#code_interface-define-get?)`boolean``false`Expects to only receive a single result from a read action or a bulk update/destroy, and returns a single result instead of a list. Sets `require_reference?` to false automatically.[`get_by`](dsl-ash-resource.html#code_interface-define-get_by)`atom | list(atom)`Takes a list of fields and adds those fields as arguments, which will then be used to filter. Sets `get?` to true and `require_reference?` to false automatically. Adds filters for read, update and destroy actions, replacing the `record` first argument.[`get_by_identity`](dsl-ash-resource.html#code_interface-define-get_by_identity)`atom`Takes an identity, gets its field list, and performs the same logic as `get_by` with those fields. Adds filters for read, update and destroy actions, replacing the `record` first argument.[`default_options`](dsl-ash-resource.html#code_interface-define-default_options)`keyword``[]`Default options to be merged with client-provided options. These can override domain or action defaults. `:load`, `:bulk_options`, and `:page` options will be deep merged. ### [](dsl-ash-resource.html#introspection-37)Introspection Target: [`Ash.Resource.Interface`](Ash.Resource.Interface.html) ### [](dsl-ash-resource.html#code_interface-define_calculation)code\_interface.define\_calculation ``` define_calculation name ``` Defines a function with the corresponding name and arguments, that evaluates a calculation. Use `:_record` to take an instance of a record. See the [code interface guide](code-interfaces.html) for more. ### [](dsl-ash-resource.html#examples-41)Examples ``` define_calculation :referral_link, args: [:id] ``` ``` define_calculation :referral_link, args: [{:arg, :id}, {:ref, :id}] ``` ### [](dsl-ash-resource.html#arguments-37)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#code_interface-define_calculation-name)`atom`The name of the function that will be defined ### [](dsl-ash-resource.html#options-29)Options NameTypeDefaultDocs[`calculation`](dsl-ash-resource.html#code_interface-define_calculation-calculation)`atom`The name of the calculation that will be evaluated. Defaults to the same name as the function.[`args`](dsl-ash-resource.html#code_interface-define_calculation-args)`any``[]`Supply field or argument values referenced by the calculation, in the form of :name, `{:arg, :name}` and/or `{:ref, :name}`. See the [code interface guide](code-interfaces.html) for more. ### [](dsl-ash-resource.html#introspection-38)Introspection Target: [`Ash.Resource.CalculationInterface`](Ash.Resource.CalculationInterface.html) ## [](dsl-ash-resource.html#resource)resource General resource configuration ### [](dsl-ash-resource.html#examples-42)Examples ``` resource do description "A description of this resource" base_filter [is_nil: :deleted_at] end ``` ### [](dsl-ash-resource.html#options-30)Options NameTypeDefaultDocs[`description`](dsl-ash-resource.html#resource-description)`String.t`A human readable description of the resource, to be used in generated documentation[`base_filter`](dsl-ash-resource.html#resource-base_filter)`any`A filter statement to be applied to any queries on the resource[`default_context`](dsl-ash-resource.html#resource-default_context)`any`Default context to apply to any queries/changesets generated for this resource.[`trace_name`](dsl-ash-resource.html#resource-trace_name)`String.t`The name to use in traces. Defaults to the short\_name stringified. See the [monitoring guide](monitoring.html) for more.[`short_name`](dsl-ash-resource.html#resource-short_name)`atom`A short identifier for the resource, which should be unique. See the [monitoring guide](monitoring.html) for more.[`plural_name`](dsl-ash-resource.html#resource-plural_name)`atom`A pluralized version of the resource short\_name. May be used by generators or automated tooling.[`require_primary_key?`](dsl-ash-resource.html#resource-require_primary_key?)`boolean``true`Allow the resource to be used without any primary key fields. Warning: this option is experimental, and should not be used unless you know what you're doing. ## [](dsl-ash-resource.html#identities)identities Unique identifiers for the resource ### [](dsl-ash-resource.html#nested-dsls-13)Nested DSLs - [identity](dsl-ash-resource.html#identities-identity) ### [](dsl-ash-resource.html#examples-43)Examples ``` identities do identity :full_name, [:first_name, :last_name] identity :email, [:email] end ``` ### [](dsl-ash-resource.html#identities-identity)identities.identity ``` identity name, keys ``` Represents a unique constraint on the resource. See the [identities guide](identities.html) for more. ### [](dsl-ash-resource.html#examples-44)Examples ``` identity :name, [:name] ``` ``` identity :full_name, [:first_name, :last_name] ``` ### [](dsl-ash-resource.html#arguments-38)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#identities-identity-name)`atom`The name of the identity.[`keys`](dsl-ash-resource.html#identities-identity-keys)`atom | list(atom)`The names of the attributes that uniquely identify this resource. ### [](dsl-ash-resource.html#options-31)Options NameTypeDefaultDocs[`where`](dsl-ash-resource.html#identities-identity-where)`any`A filter that expresses only matching records are unique on the provided keys. Ignored on embedded resources.[`nils_distinct?`](dsl-ash-resource.html#identities-identity-nils_distinct?)`boolean``true`Whether or not `nil` values are considered always distinct from eachother. `nil` values won't conflict with eachother unless you set this option to `false`.[`eager_check?`](dsl-ash-resource.html#identities-identity-eager_check?)`boolean``false`Whether or not this identity is validated to be unique at validation time.[`eager_check_with`](dsl-ash-resource.html#identities-identity-eager_check_with)`module`Validates that the unique identity provided is unique at validation time, outside of any transactions, using the domain module provided. Will default to resource's domain.[`pre_check?`](dsl-ash-resource.html#identities-identity-pre_check?)`boolean``false`Whether or not this identity is validated to be unique in a before\_action hook.[`pre_check_with`](dsl-ash-resource.html#identities-identity-pre_check_with)`module`Validates that the unique identity provided is unique in a before\_action hook.[`description`](dsl-ash-resource.html#identities-identity-description)`String.t`An optional description for the identity[`message`](dsl-ash-resource.html#identities-identity-message)`String.t`An error message to use when the unique identity would be violated[`all_tenants?`](dsl-ash-resource.html#identities-identity-all_tenants?)`boolean``false`Whether or not this identity is unique across all tenants. If the resource is not multitenant, has no effect. ### [](dsl-ash-resource.html#introspection-39)Introspection Target: [`Ash.Resource.Identity`](Ash.Resource.Identity.html) ## [](dsl-ash-resource.html#changes)changes Declare changes that occur on create/update/destroy actions against the resource See [`Ash.Resource.Change`](Ash.Resource.Change.html) for more. ### [](dsl-ash-resource.html#nested-dsls-14)Nested DSLs - [change](dsl-ash-resource.html#changes-change) ### [](dsl-ash-resource.html#examples-45)Examples ``` changes do change {Mod, [foo: :bar]} change set_context(%{some: :context}) end ``` ### [](dsl-ash-resource.html#changes-change)changes.change ``` change change ``` A change to be applied to the changeset. See [`Ash.Resource.Change`](Ash.Resource.Change.html) for more. ### [](dsl-ash-resource.html#examples-46)Examples ``` change relate_actor(:reporter) ``` ``` change {MyCustomChange, :foo} ``` ### [](dsl-ash-resource.html#arguments-39)Arguments NameTypeDefaultDocs[`change`](dsl-ash-resource.html#changes-change-change)`(any, any -> any) | module`The module and options for a change. Also accepts a function that takes the changeset and the context. See [`Ash.Resource.Change.Builtins`](Ash.Resource.Change.Builtins.html) for builtin changes. ### [](dsl-ash-resource.html#options-32)Options NameTypeDefaultDocs[`on`](dsl-ash-resource.html#changes-change-on)`:create | :update | :destroy | list(:create | :update | :destroy)``[:create, :update]`The action types the change should run on. Destroy actions are omitted by default as most changes don't make sense for a destroy.[`only_when_valid?`](dsl-ash-resource.html#changes-change-only_when_valid?)`boolean``false`If the change should only be run on valid changes. By default, all changes are run unless stated otherwise here.[`description`](dsl-ash-resource.html#changes-change-description)`String.t`An optional description for the change[`where`](dsl-ash-resource.html#changes-change-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this change to apply. These validations failing will result in this change being ignored.[`always_atomic?`](dsl-ash-resource.html#changes-change-always_atomic?)`boolean``false`By default, changes are only run atomically if all changes will be run atomically or if there is no `change/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-40)Introspection Target: [`Ash.Resource.Change`](Ash.Resource.Change.html) ## [](dsl-ash-resource.html#preparations)preparations Declare preparations that occur on all read actions for a given resource ### [](dsl-ash-resource.html#nested-dsls-15)Nested DSLs - [prepare](dsl-ash-resource.html#preparations-prepare) ### [](dsl-ash-resource.html#examples-47)Examples ``` preparations do prepare {Mod, [foo: :bar]} prepare set_context(%{some: :context}) end ``` ### [](dsl-ash-resource.html#preparations-prepare)preparations.prepare ``` prepare preparation ``` Declares a preparation, which can be used to prepare a query for a read action. ### [](dsl-ash-resource.html#examples-48)Examples ``` prepare build(sort: [:foo, :bar]) ``` ### [](dsl-ash-resource.html#arguments-40)Arguments NameTypeDefaultDocs[`preparation`](dsl-ash-resource.html#preparations-prepare-preparation)`(any, any -> any) | module`The module and options for a preparation. Also accepts functions take the query and the context. ### [](dsl-ash-resource.html#introspection-41)Introspection Target: [`Ash.Resource.Preparation`](Ash.Resource.Preparation.html) ## [](dsl-ash-resource.html#validations)validations Declare validations prior to performing actions against the resource ### [](dsl-ash-resource.html#nested-dsls-16)Nested DSLs - [validate](dsl-ash-resource.html#validations-validate) ### [](dsl-ash-resource.html#examples-49)Examples ``` validations do validate {Mod, [foo: :bar]} validate at_least_one_of_present([:first_name, :last_name]) end ``` ### [](dsl-ash-resource.html#validations-validate)validations.validate ``` validate validation ``` Declares a validation for creates and updates. See [`Ash.Resource.Validation.Builtins`](Ash.Resource.Validation.Builtins.html) or [`Ash.Resource.Validation`](Ash.Resource.Validation.html) for more. ### [](dsl-ash-resource.html#examples-50)Examples ``` validate {Mod, [foo: :bar]} ``` ``` validate at_least_one_of_present([:first_name, :last_name]) ``` ### [](dsl-ash-resource.html#arguments-41)Arguments NameTypeDefaultDocs[`validation`](dsl-ash-resource.html#validations-validate-validation)`(any, any -> any) | module`The module (or module and opts) that implements the [`Ash.Resource.Validation`](Ash.Resource.Validation.html) behaviour. Also accepts a function that receives the changeset and its context. ### [](dsl-ash-resource.html#options-33)Options NameTypeDefaultDocs[`where`](dsl-ash-resource.html#validations-validate-where)`(any, any -> any) | module | list((any, any -> any) | module)``[]`Validations that should pass in order for this validation to apply. Any of these validations failing will result in this validation being ignored.[`on`](dsl-ash-resource.html#validations-validate-on)`:create | :update | :destroy | list(:create | :update | :destroy)``[:create, :update]`The action types the validation should run on. Many validations don't make sense in the context of deletion, so by default it is not included.[`only_when_valid?`](dsl-ash-resource.html#validations-validate-only_when_valid?)`boolean``false`If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data.[`message`](dsl-ash-resource.html#validations-validate-message)`String.t`If provided, overrides any message set by the validation error[`description`](dsl-ash-resource.html#validations-validate-description)`String.t`An optional description for the validation[`before_action?`](dsl-ash-resource.html#validations-validate-before_action?)`boolean``false`If set to `true`, the validation will be run in a before\_action hook[`always_atomic?`](dsl-ash-resource.html#validations-validate-always_atomic?)`boolean``false`By default, validations are only run atomically if all changes will be run atomically or if there is no `validate/3` callback defined. Set this to `true` to run it atomically always. ### [](dsl-ash-resource.html#introspection-42)Introspection Target: [`Ash.Resource.Validation`](Ash.Resource.Validation.html) ## [](dsl-ash-resource.html#aggregates)aggregates Declare named aggregates on the resource. These are aggregates that can be loaded only by name using [`Ash.Query.load/2`](Ash.Query.html#load/2). They are also available as top level fields on the resource. See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-17)Nested DSLs - [count](dsl-ash-resource.html#aggregates-count) - join\_filter - [exists](dsl-ash-resource.html#aggregates-exists) - join\_filter - [first](dsl-ash-resource.html#aggregates-first) - join\_filter - [sum](dsl-ash-resource.html#aggregates-sum) - join\_filter - [list](dsl-ash-resource.html#aggregates-list) - join\_filter - [max](dsl-ash-resource.html#aggregates-max) - join\_filter - [min](dsl-ash-resource.html#aggregates-min) - join\_filter - [avg](dsl-ash-resource.html#aggregates-avg) - join\_filter - [custom](dsl-ash-resource.html#aggregates-custom) - join\_filter ### [](dsl-ash-resource.html#examples-51)Examples ``` aggregates do count :assigned_ticket_count, :reported_tickets do filter [active: true] end end ``` ### [](dsl-ash-resource.html#aggregates-count)aggregates.count ``` count name, relationship_path ``` Declares a named count aggregate on the resource Supports `filter`, but not `sort` (because that wouldn't affect the count) See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-18)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-count-join_filter) ### [](dsl-ash-resource.html#examples-52)Examples ``` count :assigned_ticket_count, :assigned_tickets do filter [active: true] end ``` ### [](dsl-ash-resource.html#arguments-42)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-count-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-count-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate ### [](dsl-ash-resource.html#options-34)Options NameTypeDefaultDocs[`uniq?`](dsl-ash-resource.html#aggregates-count-uniq?)`boolean``false`Whether or not to count unique values only[`read_action`](dsl-ash-resource.html#aggregates-count-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`field`](dsl-ash-resource.html#aggregates-count-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource[`filter`](dsl-ash-resource.html#aggregates-count-filter)`any``[]`A filter to apply to the aggregate[`description`](dsl-ash-resource.html#aggregates-count-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-count-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-count-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-count-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-count-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-count-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-count-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-count-join_filter)aggregates.count.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-53)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-43)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-count-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-count-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-43)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-44)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-exists)aggregates.exists ``` exists name, relationship_path ``` Declares a named `exists` aggregate on the resource Supports `filter`, but not `sort` (because that wouldn't affect if something exists) See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-19)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-exists-join_filter) ### [](dsl-ash-resource.html#examples-54)Examples ``` exists :has_ticket, :assigned_tickets ``` ### [](dsl-ash-resource.html#arguments-44)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-exists-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-exists-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate ### [](dsl-ash-resource.html#options-35)Options NameTypeDefaultDocs[`read_action`](dsl-ash-resource.html#aggregates-exists-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`filter`](dsl-ash-resource.html#aggregates-exists-filter)`any``[]`A filter to apply to the aggregate[`description`](dsl-ash-resource.html#aggregates-exists-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-exists-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-exists-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-exists-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-exists-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-exists-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-exists-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-exists-join_filter)aggregates.exists.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-55)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-45)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-exists-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-exists-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-45)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-46)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-first)aggregates.first ``` first name, relationship_path, field ``` 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`. See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-20)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-first-join_filter) ### [](dsl-ash-resource.html#examples-56)Examples ``` first :first_assigned_ticket_subject, :assigned_tickets, :subject do filter [active: true] sort [:subject] end ``` ### [](dsl-ash-resource.html#arguments-46)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-first-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-first-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate[`field`](dsl-ash-resource.html#aggregates-first-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource ### [](dsl-ash-resource.html#options-36)Options NameTypeDefaultDocs[`include_nil?`](dsl-ash-resource.html#aggregates-first-include_nil?)`boolean``false`Whether or not to include `nil` values in the aggregate. Only relevant for `list` and `first` aggregates.[`read_action`](dsl-ash-resource.html#aggregates-first-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`filter`](dsl-ash-resource.html#aggregates-first-filter)`any``[]`A filter to apply to the aggregate[`sort`](dsl-ash-resource.html#aggregates-first-sort)`any`A sort to be applied to the aggregate[`description`](dsl-ash-resource.html#aggregates-first-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-first-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-first-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-first-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-first-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-first-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-first-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-first-join_filter)aggregates.first.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-57)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-47)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-first-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-first-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-47)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-48)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-sum)aggregates.sum ``` sum name, relationship_path, field ``` Declares a named `sum` aggregate on the resource Supports `filter`, but not `sort` (because that wouldn't affect the sum) See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-21)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-sum-join_filter) ### [](dsl-ash-resource.html#examples-58)Examples ``` sum :assigned_ticket_price_sum, :assigned_tickets, :price do filter [active: true] end ``` ### [](dsl-ash-resource.html#arguments-48)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-sum-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-sum-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate[`field`](dsl-ash-resource.html#aggregates-sum-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource ### [](dsl-ash-resource.html#options-37)Options NameTypeDefaultDocs[`read_action`](dsl-ash-resource.html#aggregates-sum-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`filter`](dsl-ash-resource.html#aggregates-sum-filter)`any``[]`A filter to apply to the aggregate[`description`](dsl-ash-resource.html#aggregates-sum-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-sum-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-sum-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-sum-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-sum-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-sum-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-sum-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-sum-join_filter)aggregates.sum.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-59)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-49)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-sum-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-sum-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-49)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-50)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-list)aggregates.list ``` list name, relationship_path, field ``` Declares a named `list` aggregate on the resource. A list aggregate selects the list of all values for the given field and relationship combination. See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-22)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-list-join_filter) ### [](dsl-ash-resource.html#examples-60)Examples ``` list :assigned_ticket_prices, :assigned_tickets, :price do filter [active: true] end ``` ### [](dsl-ash-resource.html#arguments-50)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-list-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-list-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate[`field`](dsl-ash-resource.html#aggregates-list-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource ### [](dsl-ash-resource.html#options-38)Options NameTypeDefaultDocs[`include_nil?`](dsl-ash-resource.html#aggregates-list-include_nil?)`boolean``false`Whether or not to include `nil` values in the aggregate. Only relevant for `list` and `first` aggregates.[`uniq?`](dsl-ash-resource.html#aggregates-list-uniq?)`boolean``false`Whether or not to count unique values only[`read_action`](dsl-ash-resource.html#aggregates-list-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`filter`](dsl-ash-resource.html#aggregates-list-filter)`any``[]`A filter to apply to the aggregate[`sort`](dsl-ash-resource.html#aggregates-list-sort)`any`A sort to be applied to the aggregate[`description`](dsl-ash-resource.html#aggregates-list-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-list-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-list-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-list-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-list-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-list-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-list-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-list-join_filter)aggregates.list.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-61)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-51)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-list-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-list-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-51)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-52)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-max)aggregates.max ``` max name, relationship_path, field ``` Declares a named `max` aggregate on the resource Supports `filter`, but not `sort` (because that wouldn't affect the max) See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-23)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-max-join_filter) ### [](dsl-ash-resource.html#examples-62)Examples ``` max :first_assigned_ticket_subject, :assigned_tickets, :severity do filter [active: true] end ``` ### [](dsl-ash-resource.html#arguments-52)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-max-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-max-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate[`field`](dsl-ash-resource.html#aggregates-max-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource ### [](dsl-ash-resource.html#options-39)Options NameTypeDefaultDocs[`read_action`](dsl-ash-resource.html#aggregates-max-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`filter`](dsl-ash-resource.html#aggregates-max-filter)`any``[]`A filter to apply to the aggregate[`description`](dsl-ash-resource.html#aggregates-max-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-max-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-max-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-max-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-max-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-max-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-max-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-max-join_filter)aggregates.max.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-63)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-53)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-max-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-max-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-53)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-54)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-min)aggregates.min ``` min name, relationship_path, field ``` Declares a named `min` aggregate on the resource Supports `filter`, but not `sort` (because that wouldn't affect the min) See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-24)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-min-join_filter) ### [](dsl-ash-resource.html#examples-64)Examples ``` min :first_assigned_ticket_subject, :assigned_tickets, :severity do filter [active: true] end ``` ### [](dsl-ash-resource.html#arguments-54)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-min-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-min-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate[`field`](dsl-ash-resource.html#aggregates-min-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource ### [](dsl-ash-resource.html#options-40)Options NameTypeDefaultDocs[`read_action`](dsl-ash-resource.html#aggregates-min-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`filter`](dsl-ash-resource.html#aggregates-min-filter)`any``[]`A filter to apply to the aggregate[`description`](dsl-ash-resource.html#aggregates-min-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-min-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-min-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-min-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-min-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-min-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-min-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-min-join_filter)aggregates.min.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-65)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-55)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-min-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-min-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-55)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-56)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-avg)aggregates.avg ``` avg name, relationship_path, field ``` Declares a named `avg` aggregate on the resource Supports `filter`, but not `sort` (because that wouldn't affect the avg) See the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-25)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-avg-join_filter) ### [](dsl-ash-resource.html#examples-66)Examples ``` avg :assigned_ticket_price_sum, :assigned_tickets, :price do filter [active: true] end ``` ### [](dsl-ash-resource.html#arguments-56)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-avg-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-avg-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate[`field`](dsl-ash-resource.html#aggregates-avg-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource ### [](dsl-ash-resource.html#options-41)Options NameTypeDefaultDocs[`read_action`](dsl-ash-resource.html#aggregates-avg-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`filter`](dsl-ash-resource.html#aggregates-avg-filter)`any``[]`A filter to apply to the aggregate[`description`](dsl-ash-resource.html#aggregates-avg-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-avg-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-avg-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-avg-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-avg-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-avg-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-avg-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-avg-join_filter)aggregates.avg.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-67)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-57)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-avg-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-avg-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-57)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-58)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ### [](dsl-ash-resource.html#aggregates-custom)aggregates.custom ``` custom name, relationship_path, type ``` Declares a named `custom` aggregate on the resource Supports `filter` and `sort`. Custom aggregates provide an `implementation` which must implement data layer specific callbacks. See the relevant data layer documentation and the [aggregates guide](aggregates.html) for more. ### [](dsl-ash-resource.html#nested-dsls-26)Nested DSLs - [join\_filter](dsl-ash-resource.html#aggregates-custom-join_filter) ### [](dsl-ash-resource.html#examples-68)Examples ``` custom :author_names, :authors, :string do implementation {StringAgg, delimiter: ","} end ``` ### [](dsl-ash-resource.html#arguments-58)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#aggregates-custom-name)`atom`The field to place the aggregate in[`relationship_path`](dsl-ash-resource.html#aggregates-custom-relationship_path)`atom | list(atom)`The relationship or relationship path to use for the aggregate[`type`](dsl-ash-resource.html#aggregates-custom-type)`module`The type of the value returned by the aggregate ### [](dsl-ash-resource.html#options-42)Options NameTypeDefaultDocs[`implementation`](dsl-ash-resource.html#aggregates-custom-implementation)`module`The module that implements the relevant data layer callbacks[`read_action`](dsl-ash-resource.html#aggregates-custom-read_action)`atom`The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.[`field`](dsl-ash-resource.html#aggregates-custom-field)`atom`The field to aggregate. Defaults to the first field in the primary key of the resource[`filter`](dsl-ash-resource.html#aggregates-custom-filter)`any``[]`A filter to apply to the aggregate[`sort`](dsl-ash-resource.html#aggregates-custom-sort)`any`A sort to be applied to the aggregate[`description`](dsl-ash-resource.html#aggregates-custom-description)`String.t`An optional description for the aggregate[`default`](dsl-ash-resource.html#aggregates-custom-default)`any`A default value to use in cases where nil would be used. Count defaults to `0`.[`public?`](dsl-ash-resource.html#aggregates-custom-public?)`boolean``false`Whether or not the aggregate will appear in public interfaces[`filterable?`](dsl-ash-resource.html#aggregates-custom-filterable?)`boolean | :simple_equality``true`Whether or not the aggregate should be usable in filters.[`sortable?`](dsl-ash-resource.html#aggregates-custom-sortable?)`boolean``true`Whether or not the aggregate should be usable in sorts.[`sensitive?`](dsl-ash-resource.html#aggregates-custom-sensitive?)`boolean``false`Whether or not the aggregate should be considered sensitive.[`authorize?`](dsl-ash-resource.html#aggregates-custom-authorize?)`boolean``true`Whether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action. ### [](dsl-ash-resource.html#aggregates-custom-join_filter)aggregates.custom.join\_filter ``` join_filter relationship_path, filter ``` Declares a join filter on an aggregate. See the aggregates guide for more. ### [](dsl-ash-resource.html#examples-69)Examples ``` join_filter [:comments, :author], expr(active == true) ``` ### [](dsl-ash-resource.html#arguments-59)Arguments NameTypeDefaultDocs[`relationship_path`](dsl-ash-resource.html#aggregates-custom-join_filter-relationship_path)`atom | list(atom)`The relationship path on which to apply the join filter[`filter`](dsl-ash-resource.html#aggregates-custom-join_filter-filter)`any`The filter to apply. Can be an expression or a filter template. ### [](dsl-ash-resource.html#introspection-59)Introspection Target: [`Ash.Resource.Aggregate.JoinFilter`](Ash.Resource.Aggregate.JoinFilter.html) ### [](dsl-ash-resource.html#introspection-60)Introspection Target: [`Ash.Resource.Aggregate`](Ash.Resource.Aggregate.html) ## [](dsl-ash-resource.html#calculations)calculations Declare named calculations on the resource. These are calculations that can be loaded only by name using [`Ash.Query.load/2`](Ash.Query.html#load/2). They are also available as top level fields on the resource. See the [calculations guide](calculations.html) for more. ### [](dsl-ash-resource.html#nested-dsls-27)Nested DSLs - [calculate](dsl-ash-resource.html#calculations-calculate) - argument ### [](dsl-ash-resource.html#examples-70)Examples ``` calculations do calculate :full_name, :string, MyApp.MyResource.FullName end ``` ### [](dsl-ash-resource.html#calculations-calculate)calculations.calculate ``` calculate name, type, calculation \\ nil ``` Declares a named calculation on the resource. Takes a module that must adopt the [`Ash.Resource.Calculation`](Ash.Resource.Calculation.html) behaviour. See that module for more information. To ensure that the necessary fields are loaded: 1.) Specifying the `load` option on a calculation in the resource. 2.) Define a `load/3` callback in the calculation module 3.) Set `always_select?` on the attribute in question See the [calculations guide](calculations.html) for more. ### [](dsl-ash-resource.html#nested-dsls-28)Nested DSLs - [argument](dsl-ash-resource.html#calculations-calculate-argument) ### [](dsl-ash-resource.html#examples-71)Examples [`Ash.Resource.Calculation`](Ash.Resource.Calculation.html) implementation example: ``` calculate :full_name, :string, {MyApp.FullName, keys: [:first_name, :last_name]}, load: [:first_name, :last_name] ``` `expr/1` example: ``` calculate :full_name, :string, expr(first_name <> " " <> last_name) ``` Example with options: ``` calculate :full_name, :string, expr(first_name <> " " <> last_name), allow_nil?: false ``` Example with options in `do` block: ``` calculate :full_name, :string, expr(first_name <> " " <> last_name) do allow_nil? false public? true end ``` ### [](dsl-ash-resource.html#arguments-60)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#calculations-calculate-name)`atom`The field name to use for the calculation value[`type`](dsl-ash-resource.html#calculations-calculate-type)`any`The type of the calculation. See [`Ash.Type`](Ash.Type.html) for more.[`calculation`](dsl-ash-resource.html#calculations-calculate-calculation)`(any, any -> any) | module | any`The `module`, `{module, opts}` or `expr(...)` to use for the calculation. Also accepts a function that takes *a list of records* and produces a result for each record. ### [](dsl-ash-resource.html#options-43)Options NameTypeDefaultDocs[`async?`](dsl-ash-resource.html#calculations-calculate-async?)`boolean``false`[`constraints`](dsl-ash-resource.html#calculations-calculate-constraints)`keyword``[]`Constraints to provide to the type. See [`Ash.Type`](Ash.Type.html) for more.[`description`](dsl-ash-resource.html#calculations-calculate-description)`String.t`An optional description for the calculation[`public?`](dsl-ash-resource.html#calculations-calculate-public?)`boolean``false`Whether or not the calculation will appear in public interfaces.[`sensitive?`](dsl-ash-resource.html#calculations-calculate-sensitive?)`boolean``false`Whether or not references to the calculation will be considered sensitive.[`load`](dsl-ash-resource.html#calculations-calculate-load)`any``[]`A load statement to be applied if the calculation is used.[`allow_nil?`](dsl-ash-resource.html#calculations-calculate-allow_nil?)`boolean``true`Whether or not the calculation can return nil.[`filterable?`](dsl-ash-resource.html#calculations-calculate-filterable?)`boolean | :simple_equality``true`Whether or not the calculation should be usable in filters.[`sortable?`](dsl-ash-resource.html#calculations-calculate-sortable?)`boolean``true`Whether or not the calculation can be referenced in sorts. ### [](dsl-ash-resource.html#calculations-calculate-argument)calculations.calculate.argument ``` argument name, type ``` An argument to be passed into the calculation's arguments map See the [calculations guide](calculations.html) for more. ### [](dsl-ash-resource.html#examples-72)Examples ``` argument :params, :map do default %{} end ``` ``` argument :retries, :integer do allow_nil? false end ``` ### [](dsl-ash-resource.html#arguments-61)Arguments NameTypeDefaultDocs[`name`](dsl-ash-resource.html#calculations-calculate-argument-name)`atom`The name of the argument[`type`](dsl-ash-resource.html#calculations-calculate-argument-type)`module`The type of the argument. See [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#options-44)Options NameTypeDefaultDocs[`default`](dsl-ash-resource.html#calculations-calculate-argument-default)`(-> any) | mfa | any`A default value to use for the argument if not provided[`allow_nil?`](dsl-ash-resource.html#calculations-calculate-argument-allow_nil?)`boolean``true`Whether or not the argument value may be nil (or may be not provided)[`allow_expr?`](dsl-ash-resource.html#calculations-calculate-argument-allow_expr?)`boolean``false`Allow passing expressions as argument values. Expressions cannot be type validated.[`constraints`](dsl-ash-resource.html#calculations-calculate-argument-constraints)`keyword``[]`Constraints to provide to the type when casting the value. See the type's documentation and [`Ash.Type`](Ash.Type.html) for more. ### [](dsl-ash-resource.html#introspection-61)Introspection Target: [`Ash.Resource.Calculation.Argument`](Ash.Resource.Calculation.Argument.html) ### [](dsl-ash-resource.html#introspection-62)Introspection Target: [`Ash.Resource.Calculation`](Ash.Resource.Calculation.html) ## [](dsl-ash-resource.html#multitenancy)multitenancy Options for configuring the multitenancy behavior of a resource. To specify a tenant, use [`Ash.Query.set_tenant/2`](Ash.Query.html#set_tenant/2) or [`Ash.Changeset.set_tenant/2`](Ash.Changeset.html#set_tenant/2) before passing it to an operation. See the [multitenancy guide](multitenancy.html) ### [](dsl-ash-resource.html#examples-73)Examples ``` multitenancy do strategy :attribute attribute :organization_id global? true end ``` ### [](dsl-ash-resource.html#options-45)Options NameTypeDefaultDocs[`strategy`](dsl-ash-resource.html#multitenancy-strategy)`:context | :attribute``:context`Determine if multitenancy is performed with attribute filters or using data layer features.[`attribute`](dsl-ash-resource.html#multitenancy-attribute)`atom`If using the `attribute` strategy, the attribute to use, e.g `org_id`[`global?`](dsl-ash-resource.html#multitenancy-global?)`boolean``false`Whether or not the data may be accessed without setting a tenant. For example, with attribute multitenancy, this allows accessing without filtering by the tenant attribute.[`parse_attribute`](dsl-ash-resource.html#multitenancy-parse_attribute)`mfa``{Ash.Resource.Dsl, :identity, []}`An mfa ({module, function, args}) pointing to a function that takes a tenant and returns the attribute value [← Previous Page Changelog](changelog.html) [Next Page → Ash.Domain](dsl-ash-domain.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/dsls/DSL-Ash.Resource.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Embedded Resources [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/embedded-resources.md#L1 "View Source") Embedded resources are stored as maps in attributes of other resources. They are great for storing structured data, and support a whole range of useful features that resources support. For example, you can have calculations, validations, policies and even relationships on embedded resources. Here is an example of a simple embedded resource: ``` defmodule MyApp.Profile do use Ash.Resource, data_layer: :embedded # Use the atom `:embedded` as the data layer. attributes do attribute :first_name, :string, public?: true attribute :last_name, :string, public?: true end end ``` ### [](embedded-resources.html#embedded-resources-can-t-do-everything)Embedded resources can't do everything Embedded resources cannot have aggregates, or expression calculations that rely on data-layer-specific capabilities. ## [](embedded-resources.html#adding-embedded-resource-attributes)Adding embedded resource attributes Embedded resources define an [`Ash.Type`](Ash.Type.html) under the hood, meaning you can use them anywhere you would use an Ash type. ``` defmodule MyApp.User do use Ash.Resource, ... attributes do ... attribute :profile, MyApp.Profile, public?: true attribute :profiles, {:array, MyApp.Profile}, public?: true # You can also have an array of embeds end end ``` ## [](embedded-resources.html#handling-nil-values)Handling nil values By default, all fields on an embedded resource will be included in the data layer, including keys with nil values. To prevent this, add the `embed_nil_values?` option to `use Ash.Resource`. For example: ``` defmodule YourEmbed do use Ash.Resource, data_layer: :embedded, embed_nil_values?: false end ``` ## [](embedded-resources.html#editing-embedded-attributes)Editing embedded attributes If you manually supply instances of the embedded structs, the structs you provide are used with no validation. For example: ``` Ash.Changeset.for_update(user, :update, %{profile: %MyApp.Profile{first_name: "first_name", last_name: "last_name"}}) ``` However, you can also treat embedded resources like regular resources that can be "created", "updated", and "destroyed". To do this, provide maps as the input, instead of structs. In the example above, if you just wanted to change the `first_name`, you'd provide: ``` Ash.Changeset.for_update(user, :update, %{profile: %{first_name: "first_name"}}) ``` This will call the primary `update` action on the resource. This allows you to define an action on the embed, and add validations to it. For example, you might have something like this: ``` defmodule MyApp.Profile do use Ash.Resource, data_layer: :embedded # Use the atom `:embedded` as the data layer. attributes do attribute :first_name, :string, public?: true attribute :last_name, :string, public?: true end validations do validate present([:first_name, :last_name], at_least: 1) end end ``` ## [](embedded-resources.html#calculations)Calculations Calculations can be added to embedded resources. When you use an embedded resource, you declare what calculations to load via a `constraint`. For example: ``` defmodule MyApp.Profile do use Ash.Resource, data_layer: :embedded # Use the atom `:embedded` as the data layer. attributes do attribute :first_name, :string, public?: true attribute :last_name, :string, public?: true end calculations do calculate :full_name, :string, concat([:first_name, :last_name], " ") end end defmodule MyApp.User do use Ash.Resource, ... attributes do attribute :profile, MyApp.Profile do public? true constraints [load: [:full_name]] end end end ``` ## [](embedded-resources.html#determining-what-action-s-will-be-called)Determining what action(s) will be called: Remember: default actions are already implemented for a resource, with no need to add them. They are called `:create`, `:update`, `:destroy`, and `:read`. You can use those without defining them. You only need to define them if you wish to override their configuration. ### [](embedded-resources.html#single-embeds)Single Embeds - If the current value is `nil` - a `create` with the provided values - If the current value is not `nil` - an `update` with the provided values - If the current value is not `nil` and the *new value* is `nil` - a `destroy` with the original value ### [](embedded-resources.html#array-embeds)Array Embeds All values in the original array are destroyed, and all maps in the new array are used to `create` new records. ## [](embedded-resources.html#adding-a-primary-key)Adding a primary key Adding a primary key to your embedded resources is especially useful when managing lists of data. Specifically, it allows you to consider changes to elements with matching primary key values as `updates`. For example: ``` defmodule MyApp.Tag do use Ash.Resource, data_layer: :embedded attributes do uuid_primary_key :id attribute :name, :string, public?: true attribute :counter, :integer, public?: true end validations do validate {Increasing, field: :counter}, on: :update end end ``` Now, you can accept input meant to `update` individual list items. The entire list must still be provided, but any items with a matching id will be considered an `update` instead of a `destroy` + `create`. ### [](embedded-resources.html#determining-what-action-s-will-be-called-with-a-primary-key)Determining what action(s) will be called with a primary key: #### Single Embeds with primary keys - If you provide a struct, instead of a map, the value provided is used as the new relationship value directly. - If the current value is `nil` - a `create` with the provided values - If the current value is not `nil` and the primary keys match - an `update` with the provided values - If the current value is not `nil` and the primary keys *don't* match - a `destroy` of the original value and a `create` of the new value - If the current value is not `nil` and the *new value* is `nil` - a `destroy` with the original value #### Array Embeds with primary keys - If you provide structs, instead of maps, the value provided is used as the new relationship value directly. - Any values in the original list with no primary key matching in the new list are `destroy`ed. - Any values in the new list with no primary key matching in the original list are `create`d. - Any values with a primary key match in the original list and the new list are `update`d ## [](embedded-resources.html#identities)Identities Identities can be added on an embedded resource, which will ensure that for any given list, they are unique on that identity. For example, if you had an embedded resource called `Tag`, you could add an identity on `name` to ensure that nothing has duplicate tag names. ## [](embedded-resources.html#usage-in-extensions)Usage in Extensions The AshJsonApi extension exposes these attributes as maps. However, the AshGraphql extension allows you to specify a type (but not queries/mutations) for an embedded resource. If you do, instead of being treated as a `:json` type it will get its own named input object type and field type. ## [](embedded-resources.html#accessing-the-source-changeset)Accessing the source changeset When building changesets for embedded resources, the source changeset will be available in action changes under `changeset.context.__source__`. This allows you to customize the action based on the details of the parent changeset. [← Previous Page Code Interface](code-interfaces.html) [Next Page → Identities](identities.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/embedded-resources.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Encrypt Attributes [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/how-to/encrypt-attributes.livemd#L1 "View Source") [![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](encrypt-attributes.html) ``` Mix.install([{:ash, "~> 3.0"}, {:ash_cloak, "~> 0.1.0"}, {:cloak, "~> 1.1"}], consolidate_protocols: false ) Application.put_env(:my_app, MyApp.Vault, ciphers: [ default: { Cloak.Ciphers.AES.GCM, tag: "AES.GCM.V1", key: Base.decode64!("ETpvtowVAL7JmcxfqJ+XVQWzKrt1ynAkC0vT7AxfyNU="), iv_length: 12 } ] ) defmodule MyApp.Vault do use Cloak.Vault, otp_app: :my_app end MyApp.Vault.start_link() ``` ## [](encrypt-attributes.html#introduction)Introduction When dealing with PII(Personally Identifiable Information) or other sensitive data, we often want to encrypt this data, and control access to the decrypted values. To do this in [`Ash`](Ash.html), we do that with `AshCloak`. See the getting started guide in `AshCloak` for installation instructions. ## [](encrypt-attributes.html#encrypting-attributes)Encrypting attributes 1. If you have not yet, follow the getting started guide for `AshCloak` and `Cloak` 2. Add the `AshCloak` extension to your resource 3. Configure the attributes that should be encrypted 4. Add any other additional desired configuration (provided by `AshCloak`) ## [](encrypt-attributes.html#examples)Examples ``` defmodule User do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets, extensions: [AshCloak] cloak do vault MyApp.Vault attributes [:ssn] end attributes do uuid_primary_key :id attribute :ssn, :string, allow_nil?: false end actions do defaults [:read, create: [:ssn], update: [:ssn]] end end defmodule Domain do use Ash.Domain, validate_config_inclusion?: false resources do resource User do define(:create_user, action: :create, args: [:ssn]) define(:update_user, action: :update, args: [:ssn]) define(:list_users, action: :read) end end end ``` ``` {:module, Domain, <<70, 79, 82, 49, 0, 1, 255, ...>>, [ Ash.Domain.Dsl.Resources.Resource, Ash.Domain.Dsl.Resources.Options, Ash.Domain.Dsl, %{opts: [], entities: [...]}, Ash.Domain.Dsl, Ash.Domain.Dsl.Resources.Options, ... ]} ``` ## [](encrypt-attributes.html#data-is-encrypted-when-modified-and-is-not-displayed-when-inspecting)Data is encrypted when modified and is *not displayed* when inspecting. ``` user = Domain.create_user!("111-11-1111") ``` ``` #User< __meta__: #Ecto.Schema.Metadata<:loaded>, id: "bc5284fe-294a-485e-8585-06130a4bca4e", aggregates: %{}, calculations: %{}, ... > ``` ``` # AshCloak turned ssn into a calculation user.ssn ``` ``` #Ash.NotLoaded<:calculation, field: :ssn> ``` ``` # Load the value to decrypt it on-demand Ash.load!(user, :ssn).ssn ``` ``` "111-11-1111" ``` [← Previous Page Authorize Access to Resources](authorize-access-to-resources.html) [Next Page → Prevent concurrent writes](prevent-concurrent-writes.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/how-to/encrypt-attributes.livemd)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Error Handling [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/development/error-handling.md#L1 "View Source") As of 3.0, Ash uses [`Splode`](../splode/0.2.7/Splode.html) to as our basis for errors. The documentation below still applies, but it is powered by [`Splode`](../splode/0.2.7/Splode.html) under the hood. There is a difficult balance to cut between informative errors and enabling simple reactions to those errors. Since many extensions may need to work with and/or adapt their behavior based on errors coming from Ash, we need rich error messages. However, when you have a hundred different exceptions to represent the various kinds of errors a system can produce, it becomes difficult to say something like "try this code, and if it is invalid, do x, if it is forbidden, do y. To this effect, exceptions in Ash have one of four classes mapping to the top level exceptions. ## [](error-handling.html#error-classes)Error Classes - forbidden - [`Ash.Error.Forbidden`](Ash.Error.Forbidden.html) - invalid - [`Ash.Error.Invalid`](Ash.Error.Invalid.html) - framework - [`Ash.Error.Framework`](Ash.Error.Framework.html) - unknown - [`Ash.Error.Unknown`](Ash.Error.Unknown.html) Since many actions can be happening at once, we want to support the presence of multiple errors as a result of a request to Ash. We do this by grouping up the errors into one before returning or raising. We choose an exception based on the order of the exceptions listed above. If there is a single forbidden, we choose [`Ash.Error.Forbidden`](Ash.Error.Forbidden.html), if there is a single invalid, we choose [`Ash.Error.Invalid`](Ash.Error.Invalid.html) and so on. The actual errors will be included in the `errors` key on the exception. The exception's message will contain a bulleted list of all the underlying exceptions that occurred. This makes it easy to react to specific kinds of errors, as well as to react to *any/all* of the errors present. An example of a single error being raised, representing multiple underlying errors: ``` AshExample.Representative |> Ash.Changeset.for_create(:create, %{employee_id: "the best"}) |> Ash.create!() ** (Ash.Error.Invalid) Invalid Error * employee_id: must be absent. * first_name, last_name: at least 1 must be present. ``` This allows easy rescuing of the major error classes, as well as inspection of the underlying cases ``` try do AshExample.Representative |> Ash.Changeset.for_create(:create, %{employee_id: "dabes"}) |> Ash.create!() rescue e in Ash.Error.Invalid -> "Encountered #{Enum.count(e.errors)} errors" end "Encountered 2 errors" ``` This pattern does add some additional overhead when you want to rescue specific kinds of errors. For example, you may need to do something like this: ``` try do AshExample.Representative |> Ash.Changeset.for_create(:create, %{employee_id: "dabes"}) |> Ash.create!() rescue e in Ash.Error.Invalid -> case Enum.find(e.errors, &(&1.__struct__ == A.Specific.Error)) do nil -> ...handle errors error -> ...handle specific error you found end end ``` ## [](error-handling.html#generating-errors)Generating Errors When returning errors from behaviors or adding errors to a changeset/query/action input, multiple formats are supported. You can return a simple String, which will be converted into an [`Ash.Error.Unknown`](Ash.Error.Unknown.html) exception. You can also return a keyword list containing `field` or `fields` and `message`, which will be used to construct an `Ash.Error.Invalid.InvalidChanges` error. Finally, you can pass an exception directly, which will be used as is if it is an Ash error, or wrapped in an [`Ash.Error.Unknown`](Ash.Error.Unknown.html) if it is not. Technically *any* value can be used as an error, but will be wrapped in an [`Ash.Error.Unknown`](Ash.Error.Unknown.html) accordingly. ### [](error-handling.html#use-exception-modules)Use exception modules You should prefer to use the exception modules provided by Ash, or ones that you have defined manually. This allows you to document your error types, and to show those errors over API interfaces. See the section on APIs below for more. ## [](error-handling.html#examples-of-using-non-standard-errors)Examples of using non standard errors ### [](error-handling.html#keyword-list-ash-error-changes-invalidchanges)Keyword list ([`Ash.Error.Changes.InvalidChanges`](Ash.Error.Changes.InvalidChanges.html)) ``` def change(changeset, _, _) do if under_21?(changeset) do Ash.Changeset.add_error(changeset, field: :age, message: "must be 21 or older") else changeset end end ``` ### [](error-handling.html#string-ash-error-unknown-unknownerror)String ([`Ash.Error.Unknown.UnknownError`](Ash.Error.Unknown.UnknownError.html)) ``` def change(changeset, _, _) do if under_21?(changeset) do Ash.Changeset.add_error(changeset, "must be 21 or older") else changeset end end ``` ## [](error-handling.html#using-an-exception-module)Using an exception module These are all modules under `Ash.Error.*`. You can create a new one with `error.exception(options)`, and the options are documented in each exception. This documentation is missing in some cases. Go to the source code of the exception to see its special options. All of them support the `vars` option, which are values to be interpolated into the message, useful for things like translation. For example: ``` def change(changeset, _, _) do if under_21?(changeset) do error = Ash.Error.Changes.Required.exception( field: :foo, type: :attribute, resource: changeset.resource ) Ash.Changeset.add_error(changeset, error) else changeset end end ``` ### [](error-handling.html#using-a-custom-exception)Using a Custom Exception You can create a custom exception like so. This is an example of a builtin exception that you could mirror to build your own ``` defmodule MyApp.Errors.Invalid.TooYoung do @moduledoc "Used when a user who is too young is attempted to be created" use Splode.Error, fields: [:age], class: :invalid def message(error) do """ Must be 21 or older, got: #{error.age}. """ end end def change(changeset, _, _) do if under_21?(changeset) do error = MyApp.Errors.Invalid.TooYoung.exception( age: Ash.Changeset.get_attribute(changeset, :age) ) Ash.Changeset.add_error(changeset, error) else changeset end end ``` ## [](error-handling.html#showing-errors-over-apis)Showing errors over APIs AshJsonApi and AshGraphql both use a special protocol to determine how (and if) a raised or returned error should be displayed. See the relevant docs: - [handling errors in AshGraphql](../ash_graphql/handle-errors.html) - [AshJsonApi.ToJsonApiError](../ash_json_api/AshJsonApi.ToJsonApiError.html) [← Previous Page Generators](generators.html) [Next Page → Testing](testing.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/development/error-handling.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Expressions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/reference/expressions.md#L1 "View Source") Ash expressions are used in various places like calculations, filters, and policies, and are meant to be portable representations of elixir expressions. You can create an expression using the [`Ash.Expr.expr/1`](Ash.Expr.html#expr/1) macro, like so: ``` Ash.Expr.expr(1 + 2) Ash.Expr.expr(x + y) Ash.Expr.expr(post.title <> " | " <> post.subtitle) ``` ### [](expressions.html#ash-expressions-are-sql-ish)Ash Expressions are SQL-ish Ash expressions have some interesting properties in their evaluation, primarily because they are made to be portable, i.e executable in some data layer (like SQL) or executable in Elixir. In general, these expressions will behave the same way they do in Elixir. The primary difference is how `nil` values work. They behave the way that `NULL` values behave in SQL. This is primarily because this pattern is easier to replicate to various popular data layers, and is generally safer when using expressions for things like authentication. The practical implications of this are that `nil` values will "poison" many expressions, and cause them to return `nil`. For example, `x + nil` would always evaluate to `nil`. Additionally, `true and nil` will always result in `nil`, *this is also true with or and not*, i.e `true or nil` will return `nil`, and `not nil` will return `nil`. Additionally, atoms and strings compare as if the atom was a string. This is because most external data layers do not know about atoms, and so they are converted to strings before comparison. ## [](expressions.html#operators)Operators The following operators are available and they behave the same as they do in Elixir, except for the `nil` addendum above. - `==` - `!=` - `>` - `>=` - `<` - `<=` - `in` - `*` - `-` - `/` - `<>` - `||` - `&&` - `is_nil` | Only works as an operator in maps/keyword list syntax. i.e `[x: [is_nil: true]]` ## [](expressions.html#functions)Functions The following functions are built in. Data Layers can add their own functions to expressions. For example, `AshPostgres` adds `trigram_similarity` function. The following functions are built in: - `if` | Works like elixir's `if`. - [`is_nil/1`](../elixir/Kernel.html#is_nil/1) | Works like elixir's `is_nil` - `get_path/2` | i.e `get_path(value, ["foo", "bar"])`. This is what expressions like `value[:foo]["bar"]` are turned into under the hood. - `contains/2` | if one string contains another string, i.e `contains("fred", "red")` - [`length/1`](../elixir/Kernel.html#length/1) | the length of a list, i.e. `length([:foo, :bar])` - `type/2` | Cast a given value to a specific type, i.e `type(^arg(:id), :uuid)` or `type(integer_field, :string)` - `string_downcase/1` | Downcases a string - `string_join/1` | Concatenates a list of strings, and ignores any nil values - `string_join/2` | As above, but with a joiner - `string_split/1` | Splits a string on spaces - `string_split/2` | As above, but with a specific delimiter - `string_split/3` | As above, but with options. See the function for the available options. - `string_length/1` | Returns the length of a given string, as reported by [`String.length/1`](../elixir/String.html#length/1) - `string_trim/1` | Trims unicode whitespace from the beginning and the end of a string - `at/2` | Get an element from a list, i.e `at(list, 1)` - [`round/1`](../elixir/Kernel.html#round/1) | Round a float, decimal or int to 0 precision, i.e `round(num)` - `round/2` | Round a float, decimal or int to the provided precision or less, i.e `round(1.1234, 3) == 1.1234` and `round(1.12, 3) == 1.12` - String interpolation | `"#{first_name} #{last_name}"`, is remapped to the equivalent usage of `<>` - `fragment/*` | Creates a fragment of a data layer expression. See the section on fragments below. ## [](expressions.html#fragments)Fragments Fragments come in two forms. ## [](expressions.html#string-fragments)String Fragments For SQL/query-backed data layers, they will be a string with question marks for interpolation. For example: `fragment("(? + ?)", foo, bar)`. ## [](expressions.html#function-fragments)Function Fragments For elixir-backed data layers, they will be a function or an MFA that will be called with the provided arguments. For example: `fragment(&Module.add/2, foo, bar)` or `fragment({Module, :add, []}, foo, bar)`. When using anonymous functions, you can *only* use the format `&Module.function/arity`. `&Module.add/2` is okay, but `fn a, b -> Module.add(a, b) end` is not. ## [](expressions.html#sub-expressions)Sub-expressions - `exists/2` | `exists(foo.bar, name == "fred")` takes an expression scoped to the destination resource, and checks if any related entry matches. See the section on `exists` below. - `path.exists/2` | Same as `exists` but the source of the relationship is itself a nested relationship. See the section on `exists` below. - `parent/1` | Allows an expression scoped to a resource to refer to the "outer" context. Used in relationship filters and `exists` ## [](expressions.html#datetime-functions)DateTime Functions - `now/0` | Evaluates to the current time when the expression is evaluated - `today/0` | Evaluates to the current date when the expression is evaluated - `ago/2` | i.e `deleted_at > ago(7, :day)`. The available time intervals are documented in [`Ash.Type.DurationName`](Ash.Type.DurationName.html) - `from_now/2` | Same as `ago` but adds instead of subtracting - `datetime_add/3` | add an interval to a datetime, i.e `datetime_add(^datetime, 10, :hour)` - `date/3` | add an interval to a date, i.e `datetime_add(^date, 3, :day)` - `start_of_day/1-2` | Converts a date or a datetime to the correspond start of its day (at 00:00 time). ## [](expressions.html#primitives)Primitives - `cond` - `cond` is transformed to a series of `if` expressions under the hood - `item[:key] or item["key"]` - accesses keys in a map. In both cases, it prefers a matching atom key, falling back to a matching string key. This is to aid with data stores that store embeds as JSON with string keys (like AshPostgres), so that this expression behaves the same in the data layer as it does in Elixir. ## [](expressions.html#escape-hatches)Escape Hatches - `lazy/1` - Takes an MFA and evaluates it just before running the query. This is important for calculations, because the `expression/2` callback should be *stable* (returns the same value given the same input). For example `lazy({ULID, :generate, [timestamp_input]})` ## [](expressions.html#inline-aggregates)Inline Aggregates Aggregates can be referenced in-line, with their relationship path specified and any options provided that match the options given to [`Ash.Query.Aggregate.new/4`](Ash.Query.Aggregate.html#new/4). For example: ``` calculate :grade, :decimal, expr( count(answers, query: [filter: expr(correct == true)]) / count(answers, query: [filter: expr(correct == false)]) ) ``` The available aggregate kinds can also be seen in the [`Ash.Query.Aggregate`](Ash.Query.Aggregate.html) module documentation. ## [](expressions.html#templates)Templates Most of the time, when you are using an expression, you will actually be creating a `template`. In this template, you have a few references that can be used, which will be replaced when before the expression is evaluated. The following references are available. ``` ^actor(:key) # equivalent to `get_in(actor || %{}, [:key])` ^actor([:key1, :key2]) # equivalent to `get_in(actor || %{}, [:key, :key2])` ^arg(:arg_name) # equivalent to `Map.get(arguments, :arg_name)` ^context(:key) # equivalent to `get_in(context, :key)` ^context([:key1, :key2]) # equivalent to `get_in(context, [:key1, :key2])` ^ref(:key) # equivalent to referring to `key`. Allows for dynamic references ^ref([:path], :key) # equivalent to referring to `path.key`. Allows for dynamic references with dynamic (or static) paths. ``` ## [](expressions.html#custom-expressions)Custom Expressions Custom expressions allow you to extend Ash's expression language with your own expressions. To see more, see [`Ash.CustomExpression`](Ash.CustomExpression.html). To add a custom expression, configure it and recompile ash. For example: ``` config :ash, :custom_expressions, [ MyApp.CustomExpression ] ``` ``` mix deps.compile ash --force ``` These expressions will be available across all usages of Ash expressions within your application. ## [](expressions.html#filter-semantics-joins)Filter semantics &amp; joins The semantics of Ash filters are probably slightly different than what you are used to, and they are important to understand. Every filter expression is always talking about a single row, potentially "joined" to single related rows. By referencing relationships, you are implicitly doing a join. For those familiar with SQL terminology, it is equivalent to a left join, although AshPostgres can detect when it is safe to do an inner join (for performance reasons). Lets use an example of `posts` and `comments`. Given a filter like the following: ``` Ash.Query.filter(Post, comments.points > 10 and comments.tag.name == "elixir") ``` The filter refers to a *single post/comment/tag combination*. So in english, this is "posts where they have a comment with more than 10 points and *that same comment* has a tag with the name `elixir`". What this also means is that filters like the above do not compose nicely when new filters are added. For example: ``` def has_comment_with_more_points_than(query, score) do Ash.Query.filter(query, comments.points > ^score) end def has_comment_tagged(query, tag) do Ash.Query.filter(query, comments.tag.name == ^tag) end Post |> has_comment_with_more_points_than(10) |> has_comment_tagged("elixir") ``` That code *seems* like it ought to produce a filter over `Post` that would give us any post with a comment having more than 10 points, *and* with a comment tagged `elixir`. That is not the same thing as having a *single* comment that meets both those criteria. So how do we make this better? ### [](expressions.html#exists)Exists Lets rewrite the above using exists: ``` def has_comment_with_more_points_than(query, score) do Ash.Query.filter(query, exists(comments, points > ^score)) end def has_comment_tagged(query, tag) do Ash.Query.filter(query, exists(comments.tag, name == ^tag)) end Post |> has_comment_with_more_points_than(10) |> has_comment_tagged("elixir") ``` Now, they will compose properly! Generally speaking, you should use exists when you are filtering across any relationships that are `to_many` relationships \*even if you don't expect your filter to be composed. Currently, the filter syntax does not minimize(combine) these `exists/2` statements, but doing so is not complex and can be added. While unlikely, please lodge an issue if you see any performance issues with `exists`. ### [](expressions.html#exists-at-path)Exists at path Sometimes, you want the ability to say that some given row must have an existing related entry matching a filter. For example: ``` Ash.Query.filter(Post, author.exists(roles, name == :admin) and author.active) ``` While the above is not common, it can be useful in some specific circumstances, and is used under the hood by the policy authorizer when combining the filters of various resources to create a single filter. ## [](expressions.html#portability)Portability Ash expressions being portable is more important than it sounds. For example, if you were using AshPostgres and had the following calculation, which is an expression capable of being run in elixir or translated to SQL: ``` calculate :full_name, :string, expr(first_name <> " " <> last_name) ``` And you did something like the following: ``` User |> Ash.Query.load(:full_name) |> Ash.Query.sort(:full_name) |> Accounts.read!() ``` You would see that it ran a SQL query with the `full_name` calculation as SQL. This allows for sorting on that value. However, if you had something like this: ``` # data can be loaded in the query like above, or on demand later Accounts.load!(user, :full_name, reuse_values?: true) ``` you would see that no SQL queries are run. The calculation is run directly in Elixir without needing to visit the database. ## [](expressions.html#parent)Parent `Parent` is a way to "jump out" of a scoped expression. Here are some examples: ``` Ash.Query.filter(exists(open_tickets, severity >= parent(severity_threshold))) ``` ``` has_many :relevant_tickets, Ticket do no_attributes? true # this says that there is no matching source_attribute and destination_attribute on this relationship filter expr(status == :open and severity >= parent(severity_threshold)) end ``` ``` count :count_of_relevant_tickets, :open_tickets do filter expr(status == :open and severity >= parent(severity_threshold)) end ``` ### [](expressions.html#referencing-related-values)Referencing related values Related values can be references using dot delimiters, i.e `Ash.Query.filter(user.first_name == "fred")`. When referencing related values in filters, if the reference is a `has_one` or `belongs_to`, the filter does exactly what it looks like (matches if the related value matches). If it is a `has_many` or a `many_to_many`, it matches if any of the related records match. ### [](expressions.html#referencing-aggregates-and-calculations)Referencing aggregates and calculations Aggregates are simple, as all aggregates can be referenced in filter expressions (if you are using a data layer that supports aggregates). For calculations, only those that define an expression can be referenced in other expressions. Here are some examples: ``` # given a `full_name` calculation Ash.Query.filter(User, full_name == "Hob Goblin") # given a `full_name` calculation that accepts an argument called `delimiter` Ash.Query.filter(User, full_name(delimiter: "~") == "Hob~Goblin") ``` [← Previous Page Glossary](glossary.html) [Next Page → Domains](domains.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/reference/expressions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Generators [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/development/generators.md#L1 "View Source") Ash comes with multiple generators, packages as mix tasks, to help you generate and make modifications to your applications. See the documentation for each mix task for more information. What is presented here is merely an overview. ## [](generators.html#installer)Installer Ash can be installed into a project using `igniter`. Some examples of how this can work: - Install Ash &amp; AshPostgres into your current project ``` mix igniter.install ash ash_postgres ``` - Create a new mix project with Ash &amp; AshPostgres installed ``` mix archive.install hex igniter_new mix igniter.new my_project --install ash,ash_postgres ``` - Create a new phoenix project with Ash &amp; AshPostgres installed ``` mix igniter.new my_project --install ash,ash_postgres,ash_phoenix --with phx.new ``` ### [](generators.html#install-hex-archives)install hex archives The archives have to be installed to use them. This only needs to be done once, until you change elixir versions. ``` mix archive.install hex igniter_new mix archive.install hex phx_new ``` ## [](generators.html#generators)Generators - [`mix ash.gen.resource`](Mix.Tasks.Ash.Gen.Resource.html) - Generates a new [`Ash.Resource`](Ash.Resource.html) - [`mix ash.gen.domain`](Mix.Tasks.Ash.Gen.Domain.html) - Generates a new [`Ash.Domain`](Ash.Domain.html) - [`mix ash.gen.enum`](Mix.Tasks.Ash.Gen.Enum.html) - Generates a new [`Ash.Type.Enum`](Ash.Type.Enum.html) - [`mix ash.gen.base_resource`](Mix.Tasks.Ash.Gen.BaseResource.html) - Generates a new base resource. ## [](generators.html#patchers)Patchers - [`mix ash.patch.extend`](Mix.Tasks.Ash.Patch.Extend.html) - Adds an extension or extensions to a domain or resource. [← Previous Page Project Structure](project-structure.html) [Next Page → Error Handling](error-handling.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/development/generators.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Generic Actions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/actions/generic-actions.md#L1 "View Source") Generic actions are so named because there are no special rules about how they work. A generic action takes arguments and returns a value. The struct used for building input for a generic action is [`Ash.ActionInput`](Ash.ActionInput.html). ``` action :say_hello, :string do argument :name, :string, allow_nil?: false run fn input, _ -> {:ok, "Hello: #{input.arguments.name}"} end end ``` A generic action declares its arguments, return type, and implementation, as illustrated above. ### [](generic-actions.html#no-return-no-problem)No return? No problem! Generic actions can omit a return type, in which case running them returns `:ok` if successful. ``` action :schedule_job do argument :job_name, :string, allow_nil?: false run fn input, _ -> # Schedule the job :ok end end ``` For a full list of all of the available options for configuring generic actions, see [the Ash.Resource.Dsl documentation](dsl-ash-resource.html#actions-action). ## [](generic-actions.html#why-use-generic-actions)Why use generic actions? The example above could be written as a normal function in elixir, i.e ``` def say_hello(name), do: "Hello: #{name}" ``` The benefit of using generic actions instead of defining normal functions: - They can be used with api extensions like `ash_json_api` and `ash_graphql` - Their inputs are type checked and casted - They support Ash authorization patterns (i.e policies) - They can be included in the code interface of a resource - They can be made transactional with a single option (`transaction? true`) If you don't need any of the above, then there is no problem with writing regular Elixir functions! ## [](generic-actions.html#return-types-and-constraints)Return types and constraints Generic actions do not cast their return types. It is expected that the action return a valid value for the type that they declare. However, declaring additional constraints can inform API usage, and make the action more clear. For example: ``` action :priority, :integer do constraints [min: 1, max: 3] argument :status, :atom, constraints: [one_of: [:high, :medium, :low]] run fn input, _ -> case input.arguments.status do :high -> {:ok, 3} :medium -> {:ok, 2} :low -> {:ok, 1} end end end ``` #### Returning resource instances It sometimes happens that you want to make a generic action which returns an instance or instances of the resource. It's natural to assume that you can set your action's return type to the name of your resource. This won't work as resources do not define a type, unless they are embedded. In embedded resources, this won't work because the module is still being compiled, so referencing yourself as a type causes a compile error. Instead, use the `:struct` type and the `instance_of` constraint, like so: ``` action :get, :struct do constraints instance_of: __MODULE__ run # ... end ``` For returning many instances of the resource, you can set your action's return type to `{:array, :struct}` and set the `items` constraint to the name of your resource. ``` action :list_resources, {:array, :struct} do constraints items: [instance_of: __MODULE__] run # ... end ``` ## [](generic-actions.html#calling-generic-actions)Calling Generic Actions To execute a generic action in Ash, follow these steps: 1. **Prepare the action input:** Use [`Ash.ActionInput.for_action/4`](Ash.ActionInput.html#for_action/4) to specify the resource, the action and its arguments. 2. **Run the action:** Use [`Ash.run_action/2`](Ash.html#run_action/2) to execute the action with the prepared input. ### [](generic-actions.html#example-usage)Example Usage Consider an [`Ash.Resource`](Ash.Resource.html) with the action `:say_hello`: ``` action :say_hello, :string do argument :name, :string, allow_nil?: false run fn input, _ -> {:ok, "Hello: #{input.arguments.name}"} end end ``` Call this action: ``` {:ok, greeting} = Resource |> Ash.ActionInput.for_action(:say_hello, %{name: "Alice"}) |> Ash.run_action() IO.puts(greeting) # Output: Hello: Alice ``` ### [](generic-actions.html#using-code-interface)Using Code Interface You can also use [Code Interfaces](code-interfaces.html) to call actions: Given a definition like: ``` define :say_hello, args: [:name] ``` ``` {:ok, greeting} = Resource.say_hello("Alice") greeting = Resource.say_hello!("Alice") ``` [← Previous Page Destroy Actions](destroy-actions.html) [Next Page → Manual Actions](manual-actions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/actions/generic-actions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Get Started [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/tutorials/get-started.md#L1 "View Source") ### [](get-started.html#learn-with-livebook)Learn with Livebook We have a basic step by step tutorial in Livebook that introduces you to Ash. No prior Ash knowledge is required. The Livebook tutorial is self contained and separate from the documentation below. [![Run in Livebook](https://livebook.dev/badge/v1/pink.svg)](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2Fash-project%2Fash_tutorial%2Fblob%2Fmaster%2Foverview.livemd) ## [](get-started.html#goals)Goals In this guide we will: 1. Create a new Elixir application and add Ash as a dependency 2. Create a simple set of resources and see how they can be used 3. Go over some core concepts of Ash 4. Find out what material might be good to visit next ## [](get-started.html#requirements)Requirements If you want to follow along yourself, you will need the following things: 1. [Elixir and Erlang installed](https://elixir-lang.org/install.html) 2. A text editor to make the changes that we make 3. A terminal to run the examples using `iex` ## [](get-started.html#steps)Steps For this tutorial, we'll use examples based around creating a help desk. We will make the following resources: - `Helpdesk.Support.Ticket` - `Helpdesk.Support.Representative` The actions we will be able to take on these resources include: - Opening a new Ticket - Closing a Ticket - Assigning a Ticket to a representative ### [](get-started.html#create-a-new-project)Create a new project ### [](get-started.html#using-igniter-recommended)Using Igniter (recommended) First, to use `mix igniter.new`, the archive must be installed. To install it, run ``` mix archive.install hex igniter_new ``` Then, create a new project: ``` mix igniter.new helpdesk --install ash && cd helpdesk ``` If you already know that you want to use Phoenix and Ash together, you can use ``` # install the archive mix archive.install hex phx_new # use the `--with` flag to generate the project with phx.new and add Ash mix igniter.new helpdesk --install ash,ash_phoenix --with phx.new && cd helpdesk ``` It is a good idea to make it a git repository and commit the initial project. You'll be able to see what changes we made, and can save your changes once we're done. ``` # Run in your terminal git init git add -A git commit -m "first commit" git branch -M main ``` Open the project in your text editor, and we'll get started. ### [](get-started.html#want-to-skip-to-the-end)Want to skip to the end? Add the `--example` flag to get the example code add directly to your app! ``` mix igniter.new helpdesk --install ash --extend ets --example ``` Already know you want to use `AshPostgres`? Use the `--extend` argument. ``` mix igniter.new helpdesk --install ash,ash_postgres --example --extend postgres ``` Want to start with a Phoenix app setup too? Use the `--with` argument. ``` mix archive.install hex phx_new mix igniter.new helpdesk \ --install ash,ash_postgres,ash_phoenix \ --with phx.new \ --extend postgres \ --example ``` Afterwards change the active directory to the newly created folder `helpdesk`, edit `devs.exs` to reflect your database credentials and run [`mix ash.setup`](Mix.Tasks.Ash.Setup.html) which will setup your postgres database. If you like you can now browse the rest of the guide, but the code shown will already be present in your application 🥳 ### [](get-started.html#using-mix)Using Mix We first create a new project with the `--sup` flag to add a supervision tree. This will be necessary for other follow-up tutorials. ``` # In your terminal mix new --sup helpdesk && cd helpdesk ``` It is a good idea to make it a git repository and commit the initial project. You'll be able to see what changes we made, and can save your changes once we're done. ``` # Run in your terminal git init git add -A git commit -m "first commit" git branch -M main ``` Open the project in your text editor, and we'll get started. ### [](get-started.html#add-ash-to-your-application)Add Ash to your application Add the `ash` and `picosat_elixir` dependencies to your `mix.exs` ``` defp deps do [ {:ash, "~> 3.0"}, {:picosat_elixir, "~> 0.2"} ] end ``` And then run `mix deps.get && mix deps.compile` to install the dependencies #### Formatting To ensure that your code stays formatted like the examples here, you can add `:ash` as an import dependency in your `.formatter.exs`: ``` [ # ... import_deps: [..., :ash], # ... ] ``` ### [](get-started.html#picosat-installation-issues)Picosat installation issues? If you have trouble compiling `picosat_elixir`, then replace `{:picosat_elixir, "~> 0.2"}` with `{:simple_sat, "~> 0.1"}` to use a simpler (but mildly slower) solver. You can always switch back to `picosat_elixir` later once you're done with the tutorial. #### Note For more auto-formatting options, see the [Development Utilities guide](development-utilities.html). And run [`mix deps.get`](../mix/Mix.Tasks.Deps.Get.html), to install the dependency. ### [](get-started.html#building-your-first-ash-domain)Building your first Ash Domain The basic building blocks of an Ash application are Ash resources. They are tied together by a domain module, which will allow you to interact with those resources. ### [](get-started.html#creating-our-first-resource)Creating our first resource ### [](get-started.html#generators)Generators We have CLI commands that will do this for you, for example [`mix ash.gen.resource`](Mix.Tasks.Ash.Gen.Resource.html) In this getting started guide, we will create the resources by hand. This is primarily because there are not actually very many steps, and we want you to be familiar with each moving piece. For more on the generators, run [`mix help ash.gen.resource`](Mix.Tasks.Ash.Gen.Resource.html). Let's start by creating our first resource along with our first domain. We will create the following files: - The domain `Helpdesk.Support`, in `lib/helpdesk/support.ex` - Our Ticket resource `Helpdesk.Support.Ticket`, in `lib/helpdesk/support/ticket.ex`. To create the required folders and files, you can use the following command in your terminal: ``` mkdir -p lib/helpdesk/support && touch $_/ticket.ex touch lib/helpdesk/support.ex ``` Your project structure should now include the following files: ``` lib/ ├─ helpdesk/ │ ├─ support/ │ │ ├─ ticket.ex │ ├─ support.ex ``` Add the following to the files we created ``` # lib/helpdesk/support.ex defmodule Helpdesk.Support do use Ash.Domain resources do resource Helpdesk.Support.Ticket end end ``` ``` # lib/helpdesk/support/ticket.ex defmodule Helpdesk.Support.Ticket do # This turns this module into a resource use Ash.Resource, domain: Helpdesk.Support actions do # Use the default implementation of the :read action defaults [:read] # and a create action, which we'll customize later create :create end # Attributes are the simple pieces of data that exist on your resource attributes do # Add an autogenerated UUID primary key called `:id`. uuid_primary_key :id # Add a string type attribute called `:subject` attribute :subject, :string end end ``` Next, add your domain to your `config.exs`, and configure some backwards compatibility configuration. Run the following to create your `config.exs` if it doesn't already exist ``` mkdir -p config touch config/config.exs ``` and add the following contents to it. ``` # in config/config.exs import Config config :helpdesk, :ash_domains, [Helpdesk.Support] config :ash, include_embedded_source_by_default?: false, default_page_type: :keyset config :ash, :policies, no_filter_static_forbidden_reads?: false ``` ### [](get-started.html#try-our-first-resource-out)Try our first resource out Run `iex -S mix` in your project's root directory and try out the following. To create a ticket, we first make an [`Ash.Changeset`](Ash.Changeset.html) for the `:create` action of the `Helpdesk.Support.Ticket` resource. Then we pass it to the [`Ash.create!/1`](Ash.html#create!/1) function. ``` Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:create) |> Ash.create!() ``` This returns what we call a `record` which is an instance of a resource. ``` #Helpdesk.Support.Ticket< ..., id: "c0f8dc32-a018-4eb4-8656-d5810118f4ea", subject: nil, ... > ``` ### [](get-started.html#customizing-our-actions)Customizing our Actions One thing you may have noticed earlier is that we created a ticket without providing any input, and as a result our ticket had a `subject` of `nil`. Additionally, we don't have any other data on the ticket. Lets add a `status` attribute, ensure that `subject` can't be `nil`, and provide a better interface by giving the `:create` action a better name, and accepting `:subject` as part of the action. We'll start with the attribute changes: ``` # lib/helpdesk/support/ticket.ex attributes do ... attribute :subject, :string do # Don't allow `nil` values allow_nil? false # Allow this attribute to be public. By default, all attributes are private. public? true end # status is either `open` or `closed`. We can add more statuses later attribute :status, :atom do # Constraints allow you to provide extra rules for the value. # The available constraints depend on the type # See the documentation for each type to know what constraints are available # Since atoms are generally only used when we know all of the values # it provides a `one_of` constraint, that only allows those values constraints [one_of: [:open, :closed]] # The status defaulting to open makes sense default :open # We also don't want status to ever be `nil` allow_nil? false end end ``` And then replace the `:create` action with `:open`, and accept `:subject` as input. ``` # lib/helpdesk/support/ticket.ex actions do ... create :open do accept [:subject] end end ``` Let's try these changes in `iex`: We use `create!` with an exclamation point here because that will raise the error which gives a nicer view of the error in `iex` ``` # Use this to pick up changes you've made to your code, or restart your session recompile() Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:open, %{subject: "My mouse won't click!"}) |> Ash.create!() ``` And we can see our newly created ticket with a subject and a status. ``` #Helpdesk.Support.Ticket< ... id: "3c94d310-7b5e-41f0-9104-5b193b831a5d", status: :open, subject: "My mouse won't click!", ... > ``` If we didn't include a subject, or left off the arguments completely, we would see an error instead ``` ** (Ash.Error.Invalid) Invalid Error * attribute subject is required ``` ### [](get-started.html#updates-and-validations)Updates and validations Now let's add some logic to close a ticket. This time we'll add an `update` action. Here we will use a `change`. Changes allow you to customize how an action executes with very fine-grained control. There are built-in changes that are automatically available as functions, but you can define your own and pass it in as shown below. You can add multiple, and they will be run in order. See the [`Ash.Changeset`](Ash.Changeset.html) module documentation for more. ``` # lib/helpdesk/support/ticket.ex actions do ... update :close do # We don't want to accept any input here accept [] validate attribute_does_not_equal(:status, :closed) do message "Ticket is already closed" end change set_attribute(:status, :closed) # A custom change could be added like so: # # change MyCustomChange # change {MyCustomChange, opt: :val} end end ``` Try out opening and closing a ticket in `iex`: ``` # Use this to pick up changes you've made to your code, or restart your session recompile() # parenthesis so you can paste into iex ticket = ( Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:open, %{subject: "My mouse won't click!"}) |> Ash.create!() ) ticket |> Ash.Changeset.for_update(:close) |> Ash.update!() #Helpdesk.Support.Ticket< ... status: :closed, subject: "My mouse won't click!", ... > ``` What if we would try to close the ticket again? ``` ticket |> Ash.Changeset.for_update(:close) |> Ash.update!() ``` The application would halt with an error: ``` ... ** (Ash.Error.Invalid) Bread Crumbs: > Returned from bulk query update: Helpdesk.Support.Ticket.close Invalid Error * Invalid value provided for status: Ticket is already closed. ... ``` Note the 'Ticket is already closed' message that we have defined in the `attribute_does_not_equal` validation. And if we'd use the non-bang version: ``` ticket |> Ash.Changeset.for_update(:close) |> Ash.update() ``` we get an error tuple with a %Ash.Error.Invalid struct that contains the message: ``` {:error, %Ash.Error.Invalid{ ... message: "Ticket is already closed", ... ``` ### [](get-started.html#querying-without-persistence)Querying without persistence So far we haven't used a data layer that does any persistence, like storing records in a database. All that this simple resource does is return the record back to us. You can see this lack of persistence by attempting to use a `read` action: ``` Ash.read!(Helpdesk.Support.Ticket) ``` Which will raise an error explaining that there is no data to be read for that resource. In order to save our data somewhere, we need to add a data layer to our resources. Before we do that, however, let's go over how Ash allows us to work against many different data layers (or even no data layer at all). Resources without a data layer will implicitly be using [`Ash.DataLayer.Simple`](Ash.DataLayer.Simple.html). This data is not persisted anywhere, and must be provided when running queries. It provides a utility for just this purpose, [`Ash.DataLayer.Simple.set_data/2`](Ash.DataLayer.Simple.html#set_data/2). Try the following in `iex`. We will open some tickets, and close some of them, and then use [`Ash.DataLayer.Simple.set_data/2`](Ash.DataLayer.Simple.html#set_data/2) to use those tickets. ``` # Ash.Query is a macro, so it must be required require Ash.Query tickets = for i <- 0..5 do ticket = Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:open, %{subject: "Issue #{i}"}) |> Ash.create!() if rem(i, 2) == 0 do ticket |> Ash.Changeset.for_update(:close) |> Ash.update!() else ticket end end ``` Find the tickets where the subject contains `"2"`. Note that the we're setting the ticket data that we're querying using `set_data`. ``` Helpdesk.Support.Ticket |> Ash.Query.filter(contains(subject, "2")) |> Ash.DataLayer.Simple.set_data(tickets) |> Ash.read!() ``` Find the tickets that are *closed* and their subject does *not* contain `"4"` ``` Helpdesk.Support.Ticket |> Ash.Query.filter(status == :closed and not(contains(subject, "4"))) |> Ash.DataLayer.Simple.set_data(tickets) |> Ash.read!() ``` The examples above could be easily implemented with `Enum.filter`, but the real power here is to allow you to use the same tools when working with any data layer. Even though it doesn't persist data in any way, [`Ash.DataLayer.Simple`](Ash.DataLayer.Simple.html) can be useful to model static data, or be used for resources where all the actions are manual and inject data from other sources. ### [](get-started.html#adding-basic-persistence)Adding basic persistence Before we get into working with relationships, let's add some real persistence to our resource. This will let us add relationships and try out querying data. There is a built in data layer that is useful for testing and prototyping, that uses [ETS](https://elixir-lang.org/getting-started/mix-otp/ets.html). ETS (Erlang Term Storage) is OTP's in-memory database, so the data won't actually stick around beyond the lifespan of your program, but it's a simple way to try things out. To add it to your resource, modify it like so: ``` # lib/helpdesk/support/ticket.ex use Ash.Resource, domain: Helpdesk.Support, data_layer: Ash.DataLayer.Ets ``` Now we can slightly modify our code above, by removing the [`Ash.DataLayer.Simple.set_data/2`](Ash.DataLayer.Simple.html#set_data/2) calls, and we can see our persistence in action. Remember, ETS is in-memory, meaning restarting your application/iex session will remove all of the data. ``` # Use this to pick up changes you've made to your code, or restart your session recompile() require Ash.Query for i <- 0..5 do ticket = Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:open, %{subject: "Issue #{i}"}) |> Ash.create!() if rem(i, 2) == 0 do ticket |> Ash.Changeset.for_update(:close) |> Ash.update!() end end # Show the tickets where the subject contains "2" Helpdesk.Support.Ticket |> Ash.Query.filter(contains(subject, "2")) |> Ash.read!() # Show the tickets that are closed and their subject does not contain "4" Helpdesk.Support.Ticket |> Ash.Query.filter(status == :closed and not(contains(subject, "4"))) |> Ash.read!() ``` ### [](get-started.html#adding-relationships)Adding relationships Now we want to be able to assign a Ticket to a Representative. First, let's create the Representative resource: ``` # lib/helpdesk/support/representative.ex defmodule Helpdesk.Support.Representative do # This turns this module into a resource using the in memory ETS data layer use Ash.Resource, domain: Helpdesk.Support, data_layer: Ash.DataLayer.Ets actions do # Add the default simple actions defaults [:read] create :create do accept [:name] end end # Attributes are the simple pieces of data that exist on your resource attributes do # Add an autogenerated UUID primary key called `:id`. uuid_primary_key :id # Add a string type attribute called `:name` attribute :name, :string do # Make the attribute public in order to give a name when calling functions from `Ash.Changeset`. public? true end end relationships do # `has_many` means that the destination attribute is not unique, therefore many related records could exist. # We assume that the destination attribute is `representative_id` based # on the module name of this resource and that the source attribute is `id`. has_many :tickets, Helpdesk.Support.Ticket end end ``` Now let's modify our Ticket resource to have the inverse relationship to the Representative. ``` # lib/helpdesk/support/ticket.ex relationships do # belongs_to means that the destination attribute is unique, meaning only one related record could exist. # We assume that the destination attribute is `representative_id` based # on the name of this relationship and that the source attribute is `representative_id`. # We create `representative_id` automatically. belongs_to :representative, Helpdesk.Support.Representative end ``` Finally, let's add our new Representative resource to our domain module ``` # lib/helpdesk/support.ex resources do ... resource Helpdesk.Support.Representative end ``` You may notice that if you don't add the resource to your domain, or if you don't add the `belongs_to` relationship, that you'll get helpful errors at compile time. Helpful compile time validations are a core concept of Ash as we really want to ensure that your application is valid. ## [](get-started.html#working-with-relationships)Working with relationships The simplest way to work with belongs to relationships is to allow directly editing the underlying id field. ### [](get-started.html#managing-relationships)managing relationships There are a wide array of options when managing relationships, and we won't cover all of them here. See the [Managing Relationships guide](relationships.html#managing-relationships) for more. Add the `assign` action to allow us to assign a Ticket to a Representative. ``` # lib/helpdesk/support/ticket.ex update :assign do accept [:representative_id] end ``` Let's try it out in our `iex` console! Use `recompile` to pick up changes you've made to your code, or just restart your session. ``` recompile() ``` ### [](get-started.html#open-a-ticket)Open a Ticket ``` ticket = ( Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:open, %{subject: "I can't find my hand!"}) |> Ash.create!() ) ``` ### [](get-started.html#create-a-representative)Create a Representative ``` representative = ( Helpdesk.Support.Representative |> Ash.Changeset.for_create(:create, %{name: "Joe Armstrong"}) |> Ash.create!() ) ``` ### [](get-started.html#assign-that-representative-to-the-ticket)Assign that Representative to the Ticket ``` ticket |> Ash.Changeset.for_update(:assign, %{representative_id: representative.id}) |> Ash.update!() ``` ### [](get-started.html#what-next)What next? What you've seen above barely scratches the surface of what Ash can do. In a lot of ways, it will look very similar to other tools that you've seen. If all that you ever used was the above, then realistically you won't see much benefit to using Ash. Where Ash shines however, is all of the tools that can work *with* your resources. You have the ability to extend the framework yourself, and apply consistent design patterns that enable unparalleled efficiency, power and flexibility as your application grows. #### Get Help - Check out [ElixirForum](https://elixirforum.com/c/ash-framework-forum) - Join our [Discord server](https://discord.gg/D7FNG2q) - Open a [GitHub issue](https://github.com/ash-project/ash/issues/new/choose) #### Persist your data See [The AshPostgres getting started guide](../ash_postgres.html) to see how to back your resources with Postgres. This is highly recommended, as the Postgres data layer provides tons of advanced capabilities. #### Add a web API Check out [AshJsonApi](../ash_json_api.html) and [AshGraphql](../ash_graphql.html) extensions to build APIs around your resource #### Authorize access and work with users See [AshAuthentication](../ash_authentication.html) for setting up users and allowing them to log in. It supports password, magic link, oauth (google, github, apple etc.) out of the box! See the [Policies guide](policies.html) for information on how to authorize access to your resources using actors and policies. #### Clean up your code that uses Ash? Creating and using changesets manually can be verbose, and they all look very similar. Luckily, Ash has your back and can help you build high quality interfaces for you! Check out the [Code Interface Guide](code-interfaces.html) to derive things like `Helpdesk.Support.Ticket.assign!(representative.id)` [← Previous Page Home](readme.html) [Next Page → What is Ash?](what-is-ash.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/tutorials/get-started.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Glossary [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/reference/glossary.md#L1 "View Source") ## [](glossary.html#action)Action An action describes an operation that can be performed for a given resource; it is the *verb* to a resource's *noun*. Examples of actions: - User.*create* - Comment.*delete* - BlogPost.*publish* - Article.*search* Ash supports five different types of actions. `create`, `read`, `update` and `destroy` (collectively often abbreviated as CRUD), and `action`, referring to a generic action with a custom return type. A resource can define multiple actions per action type, eg. a *publish* action would be considered an `update` because it is updating an existing instance of a resource. Actions are much more flexible than simple CRUD, but these five action types serve as templates for anything you might want to do. See the [Actions guide](actions.html) for more. ## [](glossary.html#actor)Actor The entity that performs an action. Most actions are run on direct user request, eg. if a user presses a Create button on a page then the actor is the user; but an actor might also be an organization, a group, or even a device. Actors can be used in a number of places, from modifying the behavior of an action to auditing who did what in your system. They are most prominent, however, when writing [policies](glossary.html#policy). See the [Actors &amp; Authorization guide](actors-and-authorization.html) for more. ## [](glossary.html#aggregate)Aggregate An aggregate is a special type of field for a resource, one that summarizes related information of the record. A more specialized type of a [calculation](glossary.html#calculation). If a Project resource has\_many Ticket resources, an example of an aggregate on the Project might be to count the tickets associated to each project. See the [Aggregates guide](aggregates.html) for more. ## [](glossary.html#attribute)Attribute A piece of data belonging to a resource. The most basic building block; an attribute has a type and a value. For resources backed by a data layer, they typically represent a column in a database table, or a key in an object store, for example. See the [Attributes guide](attributes.html) for more. ## [](glossary.html#authorizer)Authorizer An authorizer is an extension that can be added to a resource that will be given the opportunity to modify and/or prevent requests to a resource. In practice, you will almost always be using [`Ash.Policy.Authorizer`](Ash.Policy.Authorizer.html), but you can still write your own if you need to. See the [Actors &amp; Authorization](actors-and-authorization.html) and [Policies](policies.html) guides for more. ## [](glossary.html#calculation)Calculation A calculation is a special type of field for a resource, one that is not directly stored in the data layer but generated on-demand. Typically it will derive from other information on the record, but it may come from some other data source entirely. See the [Calculations guide](calculations.html) for more. ## [](glossary.html#changeset)Changeset Changesets encapsulate data changes made while creating or updating an instance of a resource. Similarly to [Ecto changesets](https://hexdocs.pm/ecto/Ecto.Changeset.html), they include data validations but they also have their own callback hook lifecycle. See [`Ash.Changeset`](Ash.Changeset.html) for more. ## [](glossary.html#domain)Domain A method of broadly separating resources into different [domains](https://hexdocs.pm/ash/%3Chttps://en.wikipedia.org/wiki/Domain_%28software_engineering%29%3E), A.K.A [bounded contexts](https://martinfowler.com/bliki/BoundedContext.html). See the [Domains guide](domains.html) for more. ## [](glossary.html#extension)Extension A packaged bundle of code that can be included in a resource to provide additional functionality. Built-in functionality such as the resource DSL itself is provided by an extension, and libraries like AshPostgres and AshAdmin also provide extensions that you can add to your resources with just one line of code. See [Extending Resources](writing-extensions.html) for more. ## [](glossary.html#filter)Filter Filters are applied to queries to limit the data returned. They can also be applied to changesets, to ensure only data matching a certain condition is updated. For example: - Fetching Articles that include a certain search term in the title - Fetching Posts created by a specific user - Fetching Tickets updated in the last week - Updating a record only if it's version matches your in memory version (optimistic locking) See [`Ash.Filter`](Ash.Filter.html) for more. ## [](glossary.html#identity)Identity A way to uniquely identify an instance of a resource. A primary key is an example of an identity that is automatically generated; you can manually add others such as a user's email address, or a URL slug for a post. If using AshPostgres, constraints will be created by the migration generator to enforce identities at the database level. See the [Identities guide](identities.html) for more. ## [](glossary.html#notifier)Notifier Notifiers are modules that are called for each action that occurs on a resource (except generic actions). They are called at the end of transactions, meaning that if a notifier is called, it is guaranteed that the action they pertain to has completed successfully. See the [Notifiers guide](notifiers.html) for more. ## [](glossary.html#policy)Policy A set of rules defining who is authorized to perform specific actions on a resource. Common policy checks include rules such as: - Forbidding anyone other than the user who wrote a blog post, from editing it - Allowing only admins to update site-wide settings See the [Policies guide](policies.html) for more. ## [](glossary.html#query)Query The tools and functions used for reading and filtering stored data, from the data layer. See [`Ash.Query`](Ash.Query.html) for more. ## [](glossary.html#record)Record A record is an "instance" of a resource. Keep in mind that this is not an "instance" in a mutable/object-oriented sense, but rather a snapshot of the data at a given point in time. When you call a read action, you get back records. You can provide a record to an update action to determine what data is being updated. ## [](glossary.html#relationship)Relationship Relationships are named links between resources, that define how they relate to each other. Relationships can be used to signify ownership of a record, membership of a group, or can be used in filtering and querying data. See the [Relationships guide](relationships.html) for more. ## [](glossary.html#resource)Resource The central concept in Ash, a resource can be used to model all kinds of things. Most often, they will map to a data store, and represent things like rows of a database table. However, they can also be backed by external data sources, be used for validating data with no persistence at all, or even be simple containers for generic actions, completely stateless. See the [Resource DSL docs](dsl-ash-resource.html) for DSL documentation. ## [](glossary.html#tenant)Tenant Multitenancy is the siloing of your app's data into discrete non-overlapping groups, typically by customer or organization (the tenant). Ash supports multitenancy both at the code level and the data layer level (depending on the data layer; for example, AshPostgres uses schemas to fully separate data per tenant.) See the [Multitenancy guide](multitenancy.html) for more. [← Previous Page Ash.Reactor](dsl-ash-reactor.html) [Next Page → Expressions](expressions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/reference/glossary.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Identities [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/identities.md#L1 "View Source") Identities are a way to declare that a record (an instance of a resource) can be uniquely identified by a set of attributes. This information can be used in various ways throughout the framework. The primary key of the resource does not need to be listed as an identity. ## [](identities.html#defining-an-identity)Defining an identity Identities are defined at the top level of a resource module, eg. ``` defmodule MyApp.MyResource do use Ash.Resource #, ... # ... identities do # If the `email` attribute must be unique across all records identity :unique_email, [:email] # If the `username` attribute must be unique for every record with a given `site` value identity :special_usernames, [:username, :site] end end ``` See `Ash.Resource.Dsl.identities` for the full range of options available when defining identities. ## [](identities.html#using-ash-get)Using `Ash.get` This will allow these fields to be passed to [`Ash.get/3`](Ash.html#get/3), e.g `Ash.get(Resource, %{email: "foo"})`. ## [](identities.html#using-upserts)Using upserts Create actions support the `upsert?: true` option, if the data layer supports it. An `upsert?` involves checking for a conflict on some set of attributes, and translating the behavior to an update in the case one is found. By default, the primary key is used when looking for duplicates, but you can set `[upsert?: true, upsert_identity: :identity_name]` to tell it to look for conflicts on a specific identity. ## [](identities.html#creating-unique-constraints)Creating unique constraints Tools like `AshPostgres` will create unique constraints in the database automatically for each identity. These unique constraints will honor other configuration on your resource, like the `base_filter` and [attribute multitenancy](multitenancy.html#attribute-multitenancy) ## [](identities.html#eager-checking)Eager Checking Setting `eager_check?: true` on an identity will allow that identity to be checked when building a create changeset over the resource. This allows for showing quick up-front validations about whether some value is taken, for example. If the resource does not have the domain configured, you can specify the domain to use with `eager_check_with: DomainName`. If you are using `AshPhoenix.Form`, for example, 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*. The `primary?` read action is used to search for a record. This will error if you have not configured one. ## [](identities.html#pre-checking)Pre Checking `pre_check?` behaves the same as `eager_check?`, 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. [`Ash.DataLayer.Ets`](Ash.DataLayer.Ets.html) will require you to set `pre_check?` since the ETS data layer has no built in support for unique constraints. The domain can be manually specified with `pre_check_with: DomainName`. [← Previous Page Embedded Resources](embedded-resources.html) [Next Page → Notifiers](notifiers.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/identities.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Manual Actions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/actions/manual-actions.md#L1 "View Source") Manual actions allow you to control how an action is performed instead of dispatching to a data layer. To do this, specify the `manual` option with a module that adopts the appropriate behavior. Manual actions are a way to implement an action in a fully custom way. This can be a very useful escape hatch when you have something that you are finding difficult to model with Ash's builtin tools. ## [](manual-actions.html#manual-creates-updates-destroy)Manual Creates/Updates/Destroy For manual create, update and destroy actions, a module is passed that uses one of the following ([`Ash.Resource.ManualCreate`](Ash.Resource.ManualCreate.html), [`Ash.Resource.ManualUpdate`](Ash.Resource.ManualUpdate.html) and [`Ash.Resource.ManualDestroy`](Ash.Resource.ManualDestroy.html)). For example: ``` create :special_create do manual MyApp.DoCreate end # The implementation defmodule MyApp.DoCreate do use Ash.Resource.ManualCreate def create(changeset, _, _) do record = create_the_record(changeset) {:ok, record} # An `{:error, error}` tuple should be returned if something failed end end ``` The underlying record can be retrieved from `changeset.data` for update and destroy manual actions. The changeset given to the manual action will be after any `before_action` hooks, and before any `after_action` hooks. ## [](manual-actions.html#manual-read-actions)Manual Read Actions Manual read actions work the same, except the will also get the "data layer query". For AshPostgres, this means you get the ecto query that would have been run. You can use [`Ash.Query.apply_to/3`](Ash.Query.html#apply_to/3) to apply a query to records in memory. This allows you to fetch the data in a way that is not possible with the data layer, but still honor the query that was provided to. ``` # 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 ``` ### [](manual-actions.html#modifying-the-query)Modifying the query As an alternative to manual read actions, you can also provide the `modify_query` option, which takes an `MFA` and allows low level manipulation of the query just before it is dispatched to the data layer. For example: ``` read :read do modify_query {MyApp.ModifyQuery, :modify, []} end defmodule MyApp.ModifyQuery do def modify(ash_query, data_layer_query) do {:ok, modify_data_layer_query(data_layer_query)} end end ``` This can be used as a last-resort escape hatch when you want to still use resource actions but need to do something that you can't do easily with Ash tools. As with any low level escape hatch, here be dragons. [← Previous Page Generic Actions](generic-actions.html) [Next Page → Actors &amp; Authorization](actors-and-authorization.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/actions/manual-actions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.codegen (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.codegen.ex#L1 "View Source") Runs all codegen tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Codegen.html#summary)Summary ## [Functions](Mix.Tasks.Ash.Codegen.html#functions) [run(argv)](Mix.Tasks.Ash.Codegen.html#run/1) Runs all codegen tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Codegen.html#functions)Functions [](Mix.Tasks.Ash.Codegen.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.codegen.ex#L9) Runs all codegen tasks for any extension on any resource/domain in your application. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.gen.base\_resource (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/gen/ash.gen.base_resource.ex#L2 "View Source") Generates a base resource ## [](Mix.Tasks.Ash.Gen.BaseResource.html#module-example)Example ``` mix ash.gen.base_resource MyApp.Resource ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.gen.domain (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/gen/ash.gen.domain.ex#L2 "View Source") Generates an Ash.Domain ## [](Mix.Tasks.Ash.Gen.Domain.html#module-example)Example ``` mix ash.gen.domain MyApp.Accounts ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.gen.enum (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/gen/ash.gen.enum.ex#L2 "View Source") Generates an Ash.Type.Enum ## [](Mix.Tasks.Ash.Gen.Enum.html#module-example)Example ``` mix ash.gen.enum MyApp.Support.Ticket.Types.Status open,closed --short-name ticket_status ``` ## [](Mix.Tasks.Ash.Gen.Enum.html#module-options)Options - `--short-name`, `-s`: Register the type under the provided shortname, so it can be referenced like `:short_name` instead of the module name. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.generate\_livebook (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.generate_livebook.ex#L1 "View Source") Generates a Livebook for each Ash domain. ## [](Mix.Tasks.Ash.GenerateLivebook.html#module-command-line-options)Command line options - `--filename` - Specify the name of the generated Livebook file. Default: `livebook.livemd` # [](Mix.Tasks.Ash.GenerateLivebook.html#summary)Summary ## [Functions](Mix.Tasks.Ash.GenerateLivebook.html#functions) [run(argv)](Mix.Tasks.Ash.GenerateLivebook.html#run/1) Generates a Livebook for each Ash domain # [](Mix.Tasks.Ash.GenerateLivebook.html#functions)Functions [](Mix.Tasks.Ash.GenerateLivebook.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.generate_livebook.ex#L15) Generates a Livebook for each Ash domain [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.generate\_policy\_charts (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.generate_policy_chart.ex#L1 "View Source") Generates a Mermaid Flow Chart for a given resource's policies. ## [](Mix.Tasks.Ash.GeneratePolicyCharts.html#module-prerequisites)Prerequisites This mix task requires the Mermaid CLI to be installed on your system. See [https://github.com/mermaid-js/mermaid-cli](https://github.com/mermaid-js/mermaid-cli) ## [](Mix.Tasks.Ash.GeneratePolicyCharts.html#module-command-line-options)Command line options - `--only` - only generates the given Flow file - `--format` - Can be set to one of either: - `plain` - Prints just the mermaid output as text. This is the default. - `md` - Prints the mermaid diagram in a markdown code block. - `svg` - Generates an SVG - `pdf` - Generates a PDF - `png` - Generates a PNG # [](Mix.Tasks.Ash.GeneratePolicyCharts.html#summary)Summary ## [Functions](Mix.Tasks.Ash.GeneratePolicyCharts.html#functions) [run(argv)](Mix.Tasks.Ash.GeneratePolicyCharts.html#run/1) Generates a Mermaid Flow Chart for a given resource's policies. # [](Mix.Tasks.Ash.GeneratePolicyCharts.html#functions)Functions [](Mix.Tasks.Ash.GeneratePolicyCharts.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.generate_policy_chart.ex#L27) Generates a Mermaid Flow Chart for a given resource's policies. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.generate\_resource\_diagrams (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.generate_resource_diagrams.ex#L1 "View Source") Generates a Mermaid Resource Diagram for each Ash domain. ## [](Mix.Tasks.Ash.GenerateResourceDiagrams.html#module-prerequisites)Prerequisites This mix task requires the Mermaid CLI to be installed on your system. See [https://github.com/mermaid-js/mermaid-cli](https://github.com/mermaid-js/mermaid-cli) ## [](Mix.Tasks.Ash.GenerateResourceDiagrams.html#module-command-line-options)Command line options - `--type` - `er` or `class` (defaults to `class`) - `--only` - only generates for the given domain - `--format` - Can be set to one of either: - `plain` - Prints just the mermaid output as text. This is the default. - `md` - Prints the mermaid diagram in a markdown code block. - `svg` - Generates an SVG - `pdf` - Generates a PDF - `png` - Generates a PNG # [](Mix.Tasks.Ash.GenerateResourceDiagrams.html#summary)Summary ## [Functions](Mix.Tasks.Ash.GenerateResourceDiagrams.html#functions) [run(argv)](Mix.Tasks.Ash.GenerateResourceDiagrams.html#run/1) Generates Mermaid Resource Diagrams for each Ash domain # [](Mix.Tasks.Ash.GenerateResourceDiagrams.html#functions)Functions [](Mix.Tasks.Ash.GenerateResourceDiagrams.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.generate_resource_diagrams.ex#L29) Generates Mermaid Resource Diagrams for each Ash domain [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.gen.resource (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/gen/ash.gen.resource.ex#L2 "View Source") Generate and configure an Ash.Resource. If the domain does not exist, we create it. If it does, we add the resource to it if it is not already present. ## [](Mix.Tasks.Ash.Gen.Resource.html#module-example)Example ``` mix ash.gen.resource Helpdesk.Support.Ticket \ --default-actions read \ --uuid-primary-key id \ --attribute subject:string:required:public \ --relationship belongs_to:representative:Helpdesk.Support.Representative \ --timestamps \ --extend postgres,graphql ``` ## [](Mix.Tasks.Ash.Gen.Resource.html#module-options)Options - `--attribute` or `-a` - An attribute or comma separated list of attributes to add, as `name:type`. Modifiers: `primary_key`, `public`, `sensitive`, and `required`. i.e `-a name:string:required` - `--relationship` or `-r` - A relationship or comma separated list of relationships to add, as `type:name:dest`. Modifiers: `public`. `belongs_to` only modifiers: `primary_key`, `sensitive`, and `required`. i.e `-r belongs_to:author:MyApp.Accounts.Author:required` - `--default-actions` - A csv list of default action types to add. The `create` and `update` actions accept the public attributes being added. - `--uuid-primary-key` or `-u` - Adds a UUIDv4 primary key with that name. i.e `-u id` - `--uuid-v7-primary-key` - Adds a UUIDv7 primary key with that name. - `--integer-primary-key` or `-i` - Adds an integer primary key with that name. i.e `-i id` - `--domain` or `-d` - The domain module to add the resource to. i.e `-d MyApp.MyDomain`. This defaults to the resource's module name, minus the last segment. - `--extend` or `-e` - A comma separated list of modules or builtins to extend the resource with. i.e `-e postgres,Some.Extension` - `--base` or `-b` - The base module to use for the resource. i.e `-b Ash.Resource`. Requires that the module is in `config :your_app, :base_resources` - `--timestamps` or `-t` - If set adds `inserted_at` and `updated_at` timestamps to the resource. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.install (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/install/ash.install.ex#L2 "View Source") Installs Ash into a project. Should be called with `mix igniter.install ash` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.migrate (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.migrate.ex#L1 "View Source") Runs all migration tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Migrate.html#summary)Summary ## [Functions](Mix.Tasks.Ash.Migrate.html#functions) [run(argv)](Mix.Tasks.Ash.Migrate.html#run/1) Runs all migration tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Migrate.html#functions)Functions [](Mix.Tasks.Ash.Migrate.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.migrate.ex#L9) Runs all migration tasks for any extension on any resource/domain in your application. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.patch.extend (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/patch/ash.patch.extend.ex#L2 "View Source") Adds an extension or extensions to the domain/resource Extensions can either be a fully qualified module name, or one of the following list, based on the thing being extended ### [](Mix.Tasks.Ash.Patch.Extend.html#module-ash-domain)Ash.Domain - `json_api` - `AshJsonApi.Domain` - `graphql` - `AshGraphql.Domain` ### [](Mix.Tasks.Ash.Patch.Extend.html#module-ash-resource)Ash.Resource - `postgres` - `AshPostgres.DataLayer` - `sqlite` - `AshSqlite.DataLayer` - `mysql` - `AshMysql.DataLayer` - `ets` - [`Ash.DataLayer.Ets`](Ash.DataLayer.Ets.html) - `mnesia` - [`Ash.DataLayer.Mnesia`](Ash.DataLayer.Mnesia.html) - `embedded` - `data_layer: :embedded` - `json_api` - `AshJsonApi.Resource` - `graphql` - `AshGraphql.Resource` ## [](Mix.Tasks.Ash.Patch.Extend.html#module-example)Example ``` mix ash.patch.extend My.Domain.Resource postgres,Ash.Policy.Authorizer ``` [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.reset (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.reset.ex#L1 "View Source") Runs all tear down tasks for any extension on any resource/domain in your application, followed by setup tasks. # [](Mix.Tasks.Ash.Reset.html#summary)Summary ## [Functions](Mix.Tasks.Ash.Reset.html#functions) [run(argv)](Mix.Tasks.Ash.Reset.html#run/1) Runs all tear down &amp; setup tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Reset.html#functions)Functions [](Mix.Tasks.Ash.Reset.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.reset.ex#L9) Runs all tear down &amp; setup tasks for any extension on any resource/domain in your application. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.rollback (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.rollback.ex#L1 "View Source") Runs all rollback tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Rollback.html#summary)Summary ## [Functions](Mix.Tasks.Ash.Rollback.html#functions) [run(argv)](Mix.Tasks.Ash.Rollback.html#run/1) Runs all rollback tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Rollback.html#functions)Functions [](Mix.Tasks.Ash.Rollback.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.rollback.ex#L9) Runs all rollback tasks for any extension on any resource/domain in your application. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.setup (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.setup.ex#L1 "View Source") Runs all setup tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Setup.html#summary)Summary ## [Functions](Mix.Tasks.Ash.Setup.html#functions) [run(argv)](Mix.Tasks.Ash.Setup.html#run/1) Runs all setup tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.Setup.html#functions)Functions [](Mix.Tasks.Ash.Setup.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.setup.ex#L9) Runs all setup tasks for any extension on any resource/domain in your application. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # mix ash.tear\_down (ash v3.4.58) [View Source](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.tear_down.ex#L1 "View Source") Runs all tear down tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.TearDown.html#summary)Summary ## [Functions](Mix.Tasks.Ash.TearDown.html#functions) [run(argv)](Mix.Tasks.Ash.TearDown.html#run/1) Runs all tear\_down tasks for any extension on any resource/domain in your application. # [](Mix.Tasks.Ash.TearDown.html#functions)Functions [](Mix.Tasks.Ash.TearDown.html#run/1) # run(argv) [](https://github.com/ash-project/ash/blob/v3.4.58/lib/mix/tasks/ash.tear_down.ex#L9) Runs all tear\_down tasks for any extension on any resource/domain in your application. [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Monitoring [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/advanced/monitoring.md#L1 "View Source") Monitoring in Ash has two primary components, [`Ash.Tracer`](Ash.Tracer.html) and `:telemetry`. Monitoring might also be referred to as observability and instrumentation. ## [](monitoring.html#packages)Packages If you want to integrate with [Appsignal](https://www.appsignal.com), use the [AshAppsignal](../ash_appsignal.html) package, which is maintained by the core team. We believe that Appsignal is a great way to get started quickly, is relatively cost effective, and provides a great user experience. ## [](monitoring.html#telemetry)Telemetry Ash emits the following telemetry events, suffixed with `:start` and `:stop`. Start events have `system_time` measurements, and stop events have `system_time` and `duration` measurements. All times will be in the native time unit. ### [](monitoring.html#important)Important Note the mention of `:start` and `:stop` suffixes. The event below `[:ash, (domain_short_name), :create]`, is actually referring to two events, `[:ash, (domain_short_name), :create, :start]` and `[:ash, (domain_short_name), :create, :stop]`. \_Replace `(domain_short_name)` with your domain short name, from `Ash.Domain.Info.short_name`. ### [](monitoring.html#events)Events - `[:ash, (domain_short_name), :create]` - The execution of a create action. Use `resource_short_name` and `action` metadata to break down measurements. - `[:ash, (domain_short_name), :update]` - The execution of a update action. Use `resource_short_name` and `action` metadata to break down measurements. - `[:ash, (domain_short_name), :read]` - The execution of a read action. Use `resource_short_name` and `action` metadata to break down measurements. - `[:ash, (domain_short_name), :destroy]` - The execution of a destroy action. Use `resource_short_name` and `action` metadata to break down measurements. - `[:ash, (domain_short_name), :action]` - The execution of a generic action. Use `resource_short_name` and `action` metadata to break down measurements. - `[:ash, :changeset]` - A changeset being processed for a given action, i.e with `Ash.Changeset.for_create`. Use `resource_short_name` metadata to break down measurements. - `[:ash, :query]` - A query being processed for an action, with `Ash.Query.for_read`. Use `resource_short_name` metadata to break down measurements. - `[:ash, :validation]` - A validation being run on a changeset. Use `resource_short_name` and `validation` metadata to break down measurements. - `[:ash, :change]` - A change being run on a changeset. Use `resource_short_name` and `change` metadata to break down measurements. - `[:ash, :calculation]` - A calculation being computed in the app. Use `resource_short_name` and `calculation` metadata to break down measurements. - `[:ash, :before_action]` - A before\_action being run on a changeset. Use `resource_short_name` to break down measurements. - `[:ash, :after_action]` - An after\_action being run on a changeset. Use `resource_short_name` to break down measurements. - `[:ash, :preparation]` - A preparation being run on a changeset. Use `resource_short_name` and `preparation` metadata to break down measurements. - `[:ash, :request_step]` - The resolution of an internal request. Ash breaks up its operations internally into multiple requests, this can give you a high resolution insight onto the execution of those internal requests resolution. Use `name` metadata to break down measurements. - `[:ash, :flow]` - The execution of an Ash flow. Use `flow_short_name` to break down measurements. - `[:ash, :flow, :custom_step]` - The execution of a custom flow step (only if using the built in runner, which is currently the only runner). Use `flow_short_name` and `name` metadata to break down measurements. ## [](monitoring.html#tracing)Tracing Tracing is very similar to telemetry, but gives you some additional hooks to `set_span_context()` and `get_span_context()`. This allows you to "move" some piece of context between two processes. Ash will call this whenever it starts a new process to do anything. What this means is that if you are using a tracing tool or library you can ensure that any processes spawned by Ash are properly included in the trace. Additionally, you should be able to integrate a tracing library to include Ash actions/spans relatively easily by implementing the other callbacks. A tracer can be configured globally in application config. ``` config :ash, :tracer, MyApp.Tracer ``` Additionally, one can be provide when creating changesets or calling an action, i.e ``` Resource # better to put it here, as changesets are traced as well. It will be carried over to the domain action |> Ash.Changeset.for_create(:create, %{}, tracer: MyApp.Tracer) # but you can also pass it here. |> Ash.create!(tracer: MyApp.Tracer) ``` For customizing the names created for each span, see: - `Ash.Domain.Dsl.execution.trace_name` - `Ash.Resource.Dsl.resource.trace_name` ### [](monitoring.html#trace-types)Trace types These are the list of trace types. - :custom - :action - :changeset - :validation - :change - :calculation - :before\_transaction - :before\_action - :after\_transaction - :after\_action - :request\_step - :custom\_flow\_step - :flow - :query - :preparation ## [](monitoring.html#after-before-action-hooks)After/Before Action Hooks Due to the way before/after action hooks run, their execution time won't be included in the span created for the change. In practice, before/after action hooks are where the long running operations tend to be. We start a corresponding `span` and emit a telemetry event for before and after hooks, but they are only so useful. In a trace, they can highlight that "some hook" took a long time. In telemetry metrics they are of even less use. The cardinality of the metric would be extremely high, and we don't have a "name" or anything to distinguish them. To that end, you can use the macros &amp; functions available in [`Ash.Tracer`](Ash.Tracer.html) to create custom spans and/or emit custom telemetry events from your hooks. They automatically handle cases where the provided tracer is `nil`, for convenience. For example: ``` defmodule MyApp.CustomChange do use Ash.Resource.Change require Ash.Tracer def change(changeset, _, _) do changeset |> Ash.Changeset.before_action(fn changeset -> Ash.Tracer.span(:custom, "custom name", changeset.context[:private][:tracer]) do # optionally set some metadata metadata = %{...} Ash.Tracer.set_metadata(changeset.context[:private][:tracer], :custom, metadata) # will get `:start` and `:stop` suffixed events emitted Ash.Tracer.telemetry_span([:telemetry, :event, :name], metadata) do ## Your logic here end end end) end end ``` [← Previous Page Reactor](reactor.html) [Next Page → Pagination](pagination.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/advanced/monitoring.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Multitenancy [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/advanced/multitenancy.md#L1 "View Source") Multitenancy is the splitting up your data into discrete areas, typically by customer. One of the most common examples of this, is the idea of splitting up a postgres database into "schemas" one for each customer that you have. Then, when making any queries, you ensure to always specify the "schema" you are querying, and you never need to worry about data crossing over between customers. The biggest benefits of this kind of strategy are the simplification of authorization logic, and better performance. Instead of all queries from all customers needing to use the same large table, they are each instead all using their own smaller tables. Another benefit is that it is much easier to delete a single customer's data on request. In Ash, there are two primary strategies for implementing multitenancy. The first (and simplest) works for any data layer that supports filtering, and requires very little maintenance/mental overhead. It is done via expecting a given attribute to line up with the `tenant`, and is called `:attribute`. The second, is based on the data layer backing your resource, and is called `:context`. For information on context based multitenancy, see the documentation of your data layer. For example, `AshPostgres` uses postgres schemas. While the `:attribute` strategy is simple to implement, it also offers fewer advantages, primarily acting as another way to ensure your data is filtered to the correct tenant. ## [](multitenancy.html#attribute-multitenancy)Attribute Multitenancy ``` defmodule MyApp.Users do use Ash.Resource, ... multitenancy do strategy :attribute attribute :organization_id end ... relationships do belongs_to :organization, MyApp.Organization end end ``` In this case, if you were to try to run a query without specifying a tenant, you would get an error telling you that the tenant is required. Setting the tenant is done via [`Ash.Query.set_tenant/2`](Ash.Query.html#set_tenant/2) and [`Ash.Changeset.set_tenant/2`](Ash.Changeset.html#set_tenant/2). If you are using a [code interface](code-interfaces.html), you can pass `tenant:` in the options list (the final parameter). If you are using an extension, such as `AshJsonMyDomain` or `AshGraphql` the method of setting tenant context is explained in that extension's documentation. Example usage of the above: ``` # Error when not setting a tenant MyApp.Users |> Ash.Query.filter(name == "fred") |> Ash.read!() ** (Ash.Error.Invalid) * "Queries against the Helpdesk.Accounts.User resource require a tenant to be specified" (ash 1.22.0) lib/ash/domain/domain.ex:944: Ash.Domain.unwrap_or_raise!/2 # Automatically filtering by `organization_id == 1` MyApp.Users |> Ash.Query.filter(name == "fred") |> Ash.Query.set_tenant(1) |> Ash.read!() [...] # Automatically setting `organization_id` to `1` MyApp.Users |> Ash.Changeset.for_create(:create, %{name: "fred"}) |> Ash.Changeset.set_tenant(1) |> Ash.create!() %MyApp.User{organization_id: 1} # Setting tenant with a code interface that exposes `list_all` as a read action MyApp.Users.list_all(tenant: 1) ``` If you want to enable running queries *without* a tenant as well as queries with a tenant, the `global?` option supports this. You will likely need to incorporate this ability into any authorization rules though, to ensure that users from one tenant can't access other tenant's data. ``` multitenancy do strategy :attribute attribute :organization_id global? true end ``` You can also provide the `parse_attribute?` option if the tenant being set doesn't exactly match the attribute value, e.g the tenant is `org_10` and the attribute is `organization_id`, which requires just `10`. ## [](multitenancy.html#tenant-aware-identities)Tenant-Aware Identities When using identities in a multitenant resource, the tenant attribute is automatically included in the uniqueness constraints. This means that the same identity value can exist across different tenants, but must be unique within a single tenant. For example, if you have a `User` resource with an email identity, users in different organizations could have the same email address. If you need an identity to be globally unique across all tenants (like a global user email system), you can set `all_tenants?: true` on the identity. ``` defmodule MyApp.User do use Ash.Resource, ... multitenancy do strategy :attribute attribute :organization_id end identities do # This email must be unique within a tenant identity :tenant_scoped_email, [:email] # This username must be unique across all tenants identity :global_username, [:username], all_tenants?: true end end ``` Example implications: ``` # These are valid because they're in different tenants User |> Ash.Changeset.for_create(:create, %{email: "fred@example.com"}) |> Ash.Changeset.set_tenant(1) |> Ash.create!() User |> Ash.Changeset.for_create(:create, %{email: "fred@example.com"}) |> Ash.Changeset.set_tenant(2) |> Ash.create!() # This would fail because usernames are global User |> Ash.Changeset.for_create(:create, %{username: "fred"}) |> Ash.Changeset.set_tenant(1) |> Ash.create!() User |> Ash.Changeset.for_create(:create, %{username: "fred"}) |> Ash.Changeset.set_tenant(2) |> Ash.create!() # Error: username already taken ``` ## [](multitenancy.html#context-multitenancy)Context Multitenancy Context multitenancy allows for the data layer to dictate how multitenancy works. For example, a csv data layer might implement multitenancy via saving the file with different suffixes, or an API wrapping data layer might use different subdomains for the tenant. For `AshPostgres` context multitenancy, which uses postgres schemas and is referred to ash "Schema Based Multitenancy", see the [guide](../ash_postgres/schema-based-multitenancy.html) ## [](multitenancy.html#possible-values-for-tenant)Possible Values for tenant By default, the tenant value is passed directly to the relevant implementation. For example, if you are using schema multitenancy with `ash_postgres`, you might provide a schema like `organization.subdomain`. In Ash, a tenant should be identifiable by a single value, like an integer or a string. You can use the [`Ash.ToTenant`](Ash.ToTenant.html) protocol to automatically convert values into this simple value. The example below will allow you to use the same organization everywhere, and have it automatically converted into the correct schema for postgres, and the correct id for attribute-based multitenant resources. You can use this without looking up the relevant record as well, as long as the required fields used in your protocol are present. ``` Ash.Changeset.for_create(..., tenant: %MyApp.Organization{id: id}) ``` ``` # in Organization resource defimpl Ash.ToTenant do def to_tenant(%{id: id}, resource) do if Ash.Resource.Info.data_layer(resource) == AshPostgres.DataLayer && Ash.Resource.Info.multitenancy_strategy(resource) == :context do "org_#{id}" else id end end end ``` This allows you to pass an `%Organization{}` or an organization\_id around, and have that `organization_id` properly used with attribute and context-based multitenancy. [← Previous Page Timeouts](timeouts.html) [Next Page → Writing Extensions](writing-extensions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/advanced/multitenancy.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Notifiers [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/notifiers.md#L1 "View Source") ## [](notifiers.html#what-are-notifiers-for)What are notifiers for? Notifiers allow you to tap into create, update and destroy actions on a resource. Notifiers are called after the current transaction is committed, which solves a lot of problems that can happen from performing a certain kind of side effect in your action code. A common example of one such issue is using Phoenix PubSub to notify another part of your app (often a LiveView or phoenix channel) of a change. If you send a message to another process while your transaction is still open, and that process tries to look up a record you just created, it won't find it yet, because your transaction is still open! Notifiers are a solution for a certain kind of side effect, what we call "at most once" effects. An example is sending an event to an analytics system, or our pusbub example above. It is "okay" if the event is fired and some error in that process prevents it from being sent. ### [](notifiers.html#when-you-really-need-an-event-to-happen)When you really need an event to happen In these cases you are looking for something other than a notifier. For example, you may want to look into integrating [https://hexdocs.pm/oban](../oban.html) into your application, allowing you to commit a "job" in the same transaction as your changes, to be processed later. Alternatively, you could look into using [`Reactor`](../reactor/0.10.3/Reactor.html), which is designed for writing "sagas" and has first-class support for Ash via the `AshReactor` extension. ### [](notifiers.html#including-a-notifier-in-a-resource)Including a notifier in a resource If the notifier is also an extension, include it in the `notifiers` key: ``` defmodule MyResource do use Ash.Resource, notifiers: [ExampleNotifier] end ``` Configuring a notifier for a specific action or actions can be a great way to avoid complexity in the implementation of a notifier. It allows you to avoid doing things like pattern matching on the action, and treat it more like a change module, that does its work whenever it is called. ``` create :create do notifiers [ExampleNotifier] end ``` When your notifier is not an extension, and you want it to run on all actions, include it this way to avoid unnecessary compile time dependencies: ``` defmodule MyResource do use Ash.Resource, simple_notifiers: [ExampleNotifier] end ``` ## [](notifiers.html#built-in-notifiers)Built-in Notifiers Ash comes with a builtin pub\_sub notifier: [`Ash.Notifier.PubSub`](Ash.Notifier.PubSub.html). See the module documentation for more. ## [](notifiers.html#creating-your-own-notifier)Creating your own notifier A notifier is a simple extension that must implement a single callback `notify/1`. Notifiers do not have to implement an Ash DSL extension, but they may in order to configure how that notifier should behave. See [`Ash.Notifier.Notification`](Ash.Notifier.Notification.html) for the currently available fields on a notification. For more information on creating a DSL extension to configure your notifier, see the docs for [`Spark.Dsl.Extension`](../spark/2.2.40/Spark.Dsl.Extension.html). ### [](notifiers.html#notifier-performance)Notifier performance Notifiers should not do intensive synchronous work. If any heavy work needs to be done, they should delegate to something else to handle the notification, like sending it to a GenServer or GenStage. ### [](notifiers.html#example-notifier)Example notifier ``` defmodule ExampleNotifier do use Ash.Notifier def notify(%Ash.Notifier.Notification{resource: resource, action: %{type: :create}, actor: actor}) do if actor do Logger.info("#{actor.id} created a #{resource}") else Logger.info("A non-logged in user created a #{resource}") end end end ``` ## [](notifiers.html#transactions)Transactions Domain calls involving resources who's datalayer supports transactions (like Postgres), notifications are saved up and sent after the transaction is closed. For example, the domain call below ultimately results in many many database calls. ``` Post |> Ash.Changeset.for_update(:update, %{}) |> Ash.Changeset.manage_relationship(:related_posts, [1, 2, 3], type: :append) |> Ash.Changeset.manage_relationship(:related_posts, [4, 5], type: :remove) |> Ash.Changeset.manage_relationship(:comments, [10], type: :append) |> Ash.update!() ``` `Ash.Changeset.manage_relationship` doesn't leverage bulk operations yet, so it performs the following operations: - a read of the currently related posts - a read of the currently related comments - a creation of a post\_link to relate to 1 - a creation of a post\_link to relate to 2 - a creation of a post\_link to relate to 3 - a destruction of the post\_link related to 4 - a destruction of the post\_link related to 5 - an update to comment 10, to set its `post_id` to this post If all three of these resources have notifiers configured, we need to send a notification for each operation (notifications are not sent for reads). For data consistency reasons, if a data layer supports transactions, all writes are done in a transaction. However, if you try to read the record from the database that you have just received a notification about before the transaction has been closed, in a different process, the information will be wrong. For this reason, Ash accumulates notifications until they can be sent. If you need to perform multiple operations against your resources in your own transaction, you will have to handle that case yourself. To support this, [`Ash.create/2`](Ash.html#create/2), [`Ash.update/2`](Ash.html#update/2) and [`Ash.destroy/2`](Ash.html#destroy/2) support a `return_notifications?: true` option. This causes the domain call to return `{:ok, result, notifications}` in the successful case. Here is an example of how you might use it. ``` result = Ash.DataLayer.transaction(resource, fn -> {:ok, something, notifications1} = create_something() {:ok, result, notifications2} = create_another_thing(something) {:ok, notifications3} = destroy_something(something) {result, Enum.concat([notifications1, notifications2, notifications3])} end) case result do {:ok, value, notifications} -> Ash.Notifier.notify(notifications) value {:error, error} -> handle_error(error) end ``` [← Previous Page Identities](identities.html) [Next Page → Actions](actions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/notifiers.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Pagination [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/advanced/pagination.livemd#L1 "View Source") [![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](pagination.html) ``` Mix.install([{:ash, "~> 3.0"}], consolidate_protocols: false) Logger.configure(level: :warning) ``` ## [](pagination.html#pagination-in-ash)Pagination in Ash Ash has built-in support for two kinds of pagination: `offset` and `keyset`. You can perform pagination by passing the `:page` option to read actions, or using [`Ash.Query.page/2`](Ash.Query.html#page/2) on the query. The page options vary depending on which kind of pagination you want to perform. Pagination support is configured on a per-action basis. A single action can support both kinds of pagination if desired, but typically you would use one or the other. Read actions generated with `defaults [:read]` support both offset and keyset pagination, for other `read` actions you have to configure the [`pagination` section](dsl-ash-resource.html#actions-read-pagination). > ### [](pagination.html#check-the-updated-query-return-type)Check the updated query return type! > > Pagination will modify the return type of calling the query action. > > Without pagination, Ash will return a list of records. > > But *with* pagination, Ash will return an [`Ash.Page.Offset`](Ash.Page.Offset.html) struct (for offset pagination) or [`Ash.Page.Keyset`](Ash.Page.Keyset.html) struct (for keyset pagination). Both structs contain the list of records in the `results` key of the struct. ## [](pagination.html#offset-pagination)Offset Pagination Offset pagination is done via providing a `limit` and an `offset` when making queries. - The `limit` determines how many records should be returned in the query. - The `offset` describes how many records from the beginning should be skipped. ### [](pagination.html#pros-of-offset-pagination)Pros of offset pagination - Simple to think about - Possible to skip to a page by number. E.g the 5th page of 10 records is `offset: 40` - Easy to reason about what page you are currently on (if the total number of records is requested) - Can go to the last page (though data may have changed between calculating the last page details, and requesting it) ### [](pagination.html#cons-of-offset-pagination)Cons of offset pagination - Does not perform well on large datasets (if you have to ask if your dataset is "large", it probably isn't) - When moving between pages, if data was created or deleted, individual records may be missing or appear on multiple pages ## [](pagination.html#keyset-pagination)Keyset Pagination Keyset pagination is done via providing an `after` or `before` option, as well as a `limit`. - The `limit` determines how many records should be returned in the query. - The `after` or `before` value should be a `keyset` value that has been returned from a previous request. Keyset values are returned whenever there is any read action on a resource that supports keyset pagination, and they are stored in the `__metadata__` key of each record. > ### [](pagination.html#keysets-are-directly-tied-to-the-sorting-applied-to-the-query)Keysets are directly tied to the sorting applied to the query > > You can't change the sort applied to a request being paginated, and use the same keyset. If you want to change the sort, but *keep* the record who's keyset you are using in the `before` or `after` option, you must first request the individual record, with the new sort applied. Then, you can use the new keyset. ### [](pagination.html#pros-of-keyset-pagination)Pros of keyset pagination - Performs very well on large datasets (assuming indices exist on the columns being sorted on) - Behaves well as data changes. The record specified will always be the first or last item in the page ### [](pagination.html#cons-of-keyset-paginations)Cons of keyset paginations - A bit more complex to use - Can't go to a specific page number ## [](pagination.html#counting-records)Counting records When calling an action that uses pagination, the full count of records can be requested by adding the option `count: true` to the page options. Note that this will perform a second query to fetch the count, which can be expensive on large data sets. ## [](pagination.html#relationship-pagination)Relationship pagination In addition to paginating root data, Ash is also capable of paginating relationships when you load them. To do this, pass a custom query in the load and call [`Ash.Query.page/2`](Ash.Query.html#page/2) on it. This can be leveraged by extensions to provide arbitrarily nested pagination, or it can be used directly in code to split data processing when dealing with relationship with a high cardinality. ## [](pagination.html#pagination-example)Pagination example Modify the setup block and configure the log level to `:debug` to see logs from the ETS data layer. ``` Logger.configure(level: :debug) ``` ### [](pagination.html#define-some-resources-for-our-purpose)Define some resources for our purpose ``` defmodule Post do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets attributes do uuid_primary_key(:id) attribute(:title, :string, allow_nil?: false) attribute(:text, :string, allow_nil?: false) end actions do defaults(create: [:title, :text]) read :read do primary?(true) prepare(build(sort: :title)) pagination do required?(false) offset?(true) keyset?(true) countable(true) end end read :keyset do prepare(build(sort: :title)) pagination(keyset?: true) end update :add_comment do require_atomic?(false) argument(:comment, :string, allow_nil?: false) change(manage_relationship(:comment, :comments, value_is_key: :text, type: :create)) end end relationships do has_many(:comments, Comment, sort: [:created_at]) end end defmodule Comment do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets attributes do uuid_primary_key(:id) attribute(:text, :string, allow_nil?: false) create_timestamp(:created_at) end actions do defaults([:read, create: [:text, :post_id], update: [:text, :post_id]]) end relationships do belongs_to(:post, Post, sort: [:created_at]) end end defmodule Domain do use Ash.Domain, validate_config_inclusion?: false resources do resource Post do define(:list_posts, action: :read) define(:list_posts_with_keyset, action: :keyset) define(:create_post, action: :create, args: [:title, :text]) define(:add_comment_to_post, action: :add_comment, args: [:comment]) end resource(Comment) end end ``` ``` {:module, Domain, <<70, 79, 82, 49, 0, 2, 31, ...>>, [ Ash.Domain.Dsl.Resources.Resource, Ash.Domain.Dsl.Resources.Options, Ash.Domain.Dsl, %{opts: [], entities: [...]}, Ash.Domain.Dsl, Ash.Domain.Dsl.Resources.Options, ... ]} ``` ### [](pagination.html#create-5-posts-with-5-comments-each)Create 5 posts with 5 comments each ``` for post_idx <- 1..5 do post = Domain.create_post!("post #{post_idx}", "text #{post_idx}") for comment_idx <- 1..5 do Domain.add_comment_to_post!(post, "comment #{comment_idx}") end end Domain.list_posts!(load: :comments) ``` ``` [ #Post< comments: [ #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6cdea87b-cb69-4dc5-9ff3-54fb46bd70b0", text: "comment 1", created_at: ~U[2024-05-28 21:32:59.013913Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "c653e92c-fe2f-4011-84c8-ace28ebbb207", text: "comment 2", created_at: ~U[2024-05-28 21:32:59.021204Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "aa207735-0a02-4b51-b5f6-69564a2a6365", text: "comment 3", created_at: ~U[2024-05-28 21:32:59.022890Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "09f9cdfe-5a88-4f6a-a8d9-2f8aa312efb8", text: "comment 4", created_at: ~U[2024-05-28 21:32:59.024526Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "9b92edf4-e79e-4870-9dd0-9130863a9715", text: "comment 5", created_at: ~U[2024-05-28 21:32:59.026132Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... > ], __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", title: "post 1", text: "text 1", aggregates: %{}, calculations: %{}, ... >, #Post< comments: [ #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "9a87a3a0-6930-4920-9345-8227b861c2ed", text: "comment 1", created_at: ~U[2024-05-28 21:32:59.028515Z], post_id: "78cd10f0-a509-4602-861f-24652c68d54b", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "a5107151-5519-4925-ab73-aef75274cd4a", text: "comment 2", created_at: ~U[2024-05-28 21:32:59.030176Z], post_id: "78cd10f0-a509-4602-861f-24652c68d54b", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "0d7e9835-25a0-4df9-bb41-06aa964dc677", text: "comment 3", created_at: ~U[2024-05-28 21:32:59.031780Z], post_id: "78cd10f0-a509-4602-861f-24652c68d54b", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "7c6663a8-6a36-4c9a-a947-a70436add8be", text: "comment 4", created_at: ~U[2024-05-28 21:32:59.033389Z], post_id: "78cd10f0-a509-4602-861f-24652c68d54b", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "4a54ee7f-18fe-401b-9a86-7c768bc52a1d", text: "comment 5", created_at: ~U[2024-05-28 21:32:59.034976Z], post_id: "78cd10f0-a509-4602-861f-24652c68d54b", aggregates: %{}, calculations: %{}, ... > ], __meta__: #Ecto.Schema.Metadata<:loaded>, id: "78cd10f0-a509-4602-861f-24652c68d54b", title: "post 2", text: "text 2", aggregates: %{}, calculations: %{}, ... >, #Post< comments: [ #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "9d01f179-4220-4796-bb7d-63527385e36b", text: "comment 1", created_at: ~U[2024-05-28 21:32:59.037470Z], post_id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "49b7a671-bc6f-4772-b8f8-73b2a4c75b34", text: "comment 2", created_at: ~U[2024-05-28 21:32:59.039117Z], post_id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "7d2ee81c-696f-4190-8d1a-45702bfaaef2", text: "comment 3", created_at: ~U[2024-05-28 21:32:59.040795Z], post_id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "98d80b57-b911-44f5-9a63-5db90c1a0d57", text: "comment 4", created_at: ~U[2024-05-28 21:32:59.042457Z], post_id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "a0f08863-ec7f-4eba-b9f5-f9d7764dc934", text: "comment 5", created_at: ~U[2024-05-28 21:32:59.044061Z], post_id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", aggregates: %{}, calculations: %{}, ... > ], __meta__: #Ecto.Schema.Metadata<:loaded>, id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", title: "post 3", text: "text 3", aggregates: %{}, calculations: %{}, ... >, #Post< comments: [ #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "2a57aa5f-0431-4d7b-a054-3bf0fc6cb2e8", text: "comment 1", created_at: ~U[2024-05-28 21:32:59.046395Z], post_id: "91d639c2-4a2c-4931-b446-543e118644f1", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "1604094f-864e-4df3-9365-a16a77ace0ba", text: "comment 2", created_at: ~U[2024-05-28 21:32:59.048111Z], post_id: "91d639c2-4a2c-4931-b446-543e118644f1", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6153ecb4-4668-4afb-94c8-b1e57ed1a187", text: "comment 3", created_at: ~U[2024-05-28 21:32:59.049749Z], post_id: "91d639c2-4a2c-4931-b446-543e118644f1", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "0844db43-39f7-41c3-aa74-41238b0882c9", text: "comment 4", created_at: ~U[2024-05-28 21:32:59.051385Z], post_id: "91d639c2-4a2c-4931-b446-543e118644f1", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "b22db803-cad0-4d90-ada1-944f0abdd304", text: "comment 5", created_at: ~U[2024-05-28 21:32:59.053563Z], post_id: "91d639c2-4a2c-4931-b446-543e118644f1", aggregates: %{}, calculations: %{}, ... > ], __meta__: #Ecto.Schema.Metadata<:loaded>, id: "91d639c2-4a2c-4931-b446-543e118644f1", title: "post 4", text: "text 4", aggregates: %{}, calculations: %{}, ... >, #Post< comments: [ #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "7b5fc51b-8e68-441e-bcd0-e52a0158e779", text: "comment 1", created_at: ~U[2024-05-28 21:32:59.056055Z], post_id: "b0b20225-17f0-4bd1-8bd1-681e63ee26a8", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "e3f01413-c79c-44ef-abd9-6cb27a3b31fc", text: "comment 2", created_at: ~U[2024-05-28 21:32:59.057708Z], post_id: "b0b20225-17f0-4bd1-8bd1-681e63ee26a8", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "a461c559-5036-4113-93be-3f531af4d2f3", text: "comment 3", created_at: ~U[2024-05-28 21:32:59.059418Z], post_id: "b0b20225-17f0-4bd1-8bd1-681e63ee26a8", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "a704a781-3ff2-479c-b428-d8a414223f00", text: "comment 4", created_at: ~U[2024-05-28 21:32:59.061034Z], post_id: "b0b20225-17f0-4bd1-8bd1-681e63ee26a8", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "2d9e9279-ef21-4dd4-bdc6-adc3597fefb2", text: "comment 5", created_at: ~U[2024-05-28 21:32:59.062631Z], post_id: "b0b20225-17f0-4bd1-8bd1-681e63ee26a8", aggregates: %{}, calculations: %{}, ... > ], __meta__: #Ecto.Schema.Metadata<:loaded>, id: "b0b20225-17f0-4bd1-8bd1-681e63ee26a8", title: "post 5", text: "text 5", aggregates: %{}, calculations: %{}, ... > ] ``` ## [](pagination.html#offset-pagination-1)Offset pagination When using offset pagination, a `%Ash.Page.Offset{}` struct is returned from read actions. ``` page = Domain.list_posts!(page: [limit: 2]) ``` ``` %Ash.Page.Offset{ results: [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", title: "post 1", text: "text 1", aggregates: %{}, calculations: %{}, ... >, #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "78cd10f0-a509-4602-861f-24652c68d54b", title: "post 2", text: "text 2", aggregates: %{}, calculations: %{}, ... > ], limit: 2, offset: 0, count: nil, rerun: {#Ash.Query< resource: Post, sort: [title: :asc], select: [:id, :title, :text], page: [limit: 2] >, [authorize?: true, reuse_values?: false, return_query?: false]}, more?: true } ``` You can find the results in the `results` field of the page ``` page.results ``` ``` [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", title: "post 1", text: "text 1", aggregates: %{}, calculations: %{}, ... >, #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "78cd10f0-a509-4602-861f-24652c68d54b", title: "post 2", text: "text 2", aggregates: %{}, calculations: %{}, ... > ] ``` The `more?` field contains a boolean indicating if there are more pages available ``` page.more? ``` ``` true ``` ### [](pagination.html#retrieving-the-next-page)Retrieving the next page You can calculate the next offset with the information available in the page and pass it in the page options to retrieve the following page ``` next_offset = page.offset + page.limit second_page = Domain.list_posts!(page: [limit: 2, offset: next_offset]) ``` ``` %Ash.Page.Offset{ results: [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", title: "post 3", text: "text 3", aggregates: %{}, calculations: %{}, ... >, #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "91d639c2-4a2c-4931-b446-543e118644f1", title: "post 4", text: "text 4", aggregates: %{}, calculations: %{}, ... > ], limit: 2, offset: 2, count: nil, rerun: {#Ash.Query< resource: Post, sort: [title: :asc], select: [:id, :title, :text], page: [limit: 2, offset: 2] >, [authorize?: true, reuse_values?: false, return_query?: false]}, more?: true } ``` If you have the current page in memory, you can also use [`Ash.page!/2`](Ash.html#page!/2) to navigate between pages. ``` last_page = Ash.page!(second_page, :next) ``` ``` %Ash.Page.Offset{ results: [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "b0b20225-17f0-4bd1-8bd1-681e63ee26a8", title: "post 5", text: "text 5", aggregates: %{}, calculations: %{}, ... > ], limit: 2, offset: 4, count: nil, rerun: {#Ash.Query< resource: Post, sort: [title: :asc], select: [:title, :id, :text], page: [offset: 4, limit: 2] >, [authorize?: true, reuse_values?: false, return_query?: false]}, more?: false } ``` And since we had 5 posts, this should be the last page: ``` last_page.more? ``` ``` false ``` ### [](pagination.html#keyset-pagination-1)Keyset pagination When using keyset pagination, a `%Ash.Page.Keyset{}` struct is returned from read actions. ``` page = Domain.list_posts_with_keyset!(page: [limit: 2]) ``` ``` %Ash.Page.Keyset{ results: [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", title: "post 1", text: "text 1", aggregates: %{}, calculations: %{}, ... >, #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "78cd10f0-a509-4602-861f-24652c68d54b", title: "post 2", text: "text 2", aggregates: %{}, calculations: %{}, ... > ], count: nil, before: nil, after: nil, limit: 2, rerun: {#Ash.Query< resource: Post, sort: [title: :asc], select: [:id, :title, :text], page: [limit: 2] >, [authorize?: true, reuse_values?: false, return_query?: false]}, more?: true } ``` `results` and `more?` work in the same way as offset pagination ``` page.results ``` ``` [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", title: "post 1", text: "text 1", aggregates: %{}, calculations: %{}, ... >, #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "78cd10f0-a509-4602-861f-24652c68d54b", title: "post 2", text: "text 2", aggregates: %{}, calculations: %{}, ... > ] ``` ### [](pagination.html#retrieving-the-next-page-1)Retrieving the next page To retrieve the next page, you have to pass the keyset of the last record in the current page. The keyset is stored in `record.__metadata__.keyset`. ``` last_keyset = page.results |> List.last() |> Map.get(:__metadata__) |> Map.get(:keyset) second_page = Domain.list_posts_with_keyset!(page: [limit: 2, after: last_keyset]) ``` ``` %Ash.Page.Keyset{ results: [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", title: "post 3", text: "text 3", aggregates: %{}, calculations: %{}, ... >, #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "91d639c2-4a2c-4931-b446-543e118644f1", title: "post 4", text: "text 4", aggregates: %{}, calculations: %{}, ... > ], count: nil, before: nil, after: "g2wAAAACbQAAAAZwb3N0IDJtAAAAJDc4Y2QxMGYwLWE1MDktNDYwMi04NjFmLTI0NjUyYzY4ZDU0Ymo=", limit: 2, rerun: {#Ash.Query< resource: Post, sort: [title: :asc], select: [:id, :title, :text], page: [ limit: 2, after: "g2wAAAACbQAAAAZwb3N0IDJtAAAAJDc4Y2QxMGYwLWE1MDktNDYwMi04NjFmLTI0NjUyYzY4ZDU0Ymo=" ] >, [authorize?: true, reuse_values?: false, return_query?: false]}, more?: true } ``` [`Ash.page!/2`](Ash.html#page!/2) works with keyset pagination too ``` last_page = Ash.page!(second_page, :next) last_page.more? ``` ``` false ``` ### [](pagination.html#actions-supporting-both-offset-and-keyset-pagination)Actions supporting both offset and keyset pagination If an action supports both offset and keyset pagination (e.g. default read actions), offset pagination is used by default when page options only contain `limit`. However, the records will have the keyset in the metadata, so keyset pagination can be performed on next pages. ``` %Ash.Page.Offset{results: [_, last]} = Domain.list_posts!(page: [limit: 2]) Domain.list_posts!(page: [limit: 2, after: last.__metadata__.keyset]) ``` ``` %Ash.Page.Keyset{ results: [ #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "ab8e9909-2a6c-42d7-bae9-09fad4356ea4", title: "post 3", text: "text 3", aggregates: %{}, calculations: %{}, ... >, #Post< comments: #Ash.NotLoaded<:relationship, field: :comments>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "91d639c2-4a2c-4931-b446-543e118644f1", title: "post 4", text: "text 4", aggregates: %{}, calculations: %{}, ... > ], count: nil, before: nil, after: "g2wAAAACbQAAAAZwb3N0IDJtAAAAJDc4Y2QxMGYwLWE1MDktNDYwMi04NjFmLTI0NjUyYzY4ZDU0Ymo=", limit: 2, rerun: {#Ash.Query< resource: Post, sort: [title: :asc], select: [:id, :title, :text], page: [ limit: 2, after: "g2wAAAACbQAAAAZwb3N0IDJtAAAAJDc4Y2QxMGYwLWE1MDktNDYwMi04NjFmLTI0NjUyYzY4ZDU0Ymo=" ] >, [authorize?: true, reuse_values?: false, return_query?: false]}, more?: true } ``` ### [](pagination.html#retrieving-count)Retrieving count Both `%Ash.Page.Offset{}` and `%Ash.Page.Keyset{}` have a `count` field that contains the total count of the items that are being paginated when `count: true` is passed in the page options. ``` page = Domain.list_posts!(page: [limit: 2, count: true]) page.count ``` ``` 5 ``` ### [](pagination.html#relationship-pagination-1)Relationship pagination To paginate a relationship, pass a query customized with the page options to the load statement. This works both on paginated and unpaginated root data, and relationships can load arbitrarily nested paginated relationships. ``` paginated_comments = Comment |> Ash.Query.page(limit: 2) first_post = Domain.list_posts!(load: [comments: paginated_comments]) |> List.first() first_post.comments ``` ``` %Ash.Page.Offset{ results: [ #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "6cdea87b-cb69-4dc5-9ff3-54fb46bd70b0", text: "comment 1", created_at: ~U[2024-05-28 21:32:59.013913Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "c653e92c-fe2f-4011-84c8-ace28ebbb207", text: "comment 2", created_at: ~U[2024-05-28 21:32:59.021204Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... > ], limit: 2, offset: 0, count: nil, rerun: {#Ash.Query<resource: Comment, sort: [created_at: :asc], page: [limit: 2]>, [authorize?: true, actor: nil, tracer: []]}, more?: true } ``` You can use all the methods describe above to navigate relationship pages and retrieve their count ``` second = Ash.page!(first_post.comments, :next) ``` ``` %Ash.Page.Offset{ results: [ #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "aa207735-0a02-4b51-b5f6-69564a2a6365", text: "comment 3", created_at: ~U[2024-05-28 21:32:59.022890Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... >, #Comment< post: #Ash.NotLoaded<:relationship, field: :post>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "09f9cdfe-5a88-4f6a-a8d9-2f8aa312efb8", text: "comment 4", created_at: ~U[2024-05-28 21:32:59.024526Z], post_id: "6eb22ea7-184c-4cae-9054-0d1a0474db61", aggregates: %{}, calculations: %{}, ... > ], limit: 2, offset: 2, count: nil, rerun: {#Ash.Query< resource: Comment, sort: [created_at: :asc], select: [:id, :text, :created_at, :post_id], page: [offset: 2, limit: 2] >, [reuse_values?: false, return_query?: false, authorize?: true, actor: nil, tracer: []]}, more?: true } ``` [← Previous Page Monitoring](monitoring.html) [Next Page → Timeouts](timeouts.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/advanced/pagination.livemd)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Policies [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/security/policies.md#L1 "View Source") Policies determine what actions on a resource are permitted for a given actor, and can also filter the results of read actions to restrict the results to only records that should be visible. To restrict access to specific fields (attributes, aggregates, calculations), see the section on field policies. Read and understand the [Actors &amp; Authorization guide](actors-and-authorization.html) before proceeding, which explains actors, how to set them, and other relevant configurations. ## [](policies.html#setup)Setup You'll need to add the extension to your resource, like so: ``` use Ash.Resource, authorizers: [Ash.Policy.Authorizer] ``` Then you can start defining policies for your resource. ## [](policies.html#policies)Policies ### [](policies.html#anatomy-of-a-policy)Anatomy of a Policy Each policy defined in a resource has two parts - - a condition or a list of conditions, such as `action_type(:read)`, `[action_type(:read), actor_attribute_equals(:admin, true)]` or `always()`. If the condition, or all conditions if given a list are true for a given action request, then the policy will be applied to the request. - a set of policy checks, each of which will be evaluated individually if a policy applies to a request. If more than one policy applies to any given request (eg. an admin actor calls a read action) then **all applicable policies must pass** for the action to be performed. A policy will produce one of three results: `:forbidden`, `:authorized`, or `:unknown`. `:unknown` is treated the same as `:forbidden`. ### [](policies.html#the-simplest-policy)The Simplest Policy Let's start with the simplest (most permissive) policy: ``` policies do policy always() do authorize_if always() end end ``` The first argument to `policy` is the condition. In this case, the condition is `always()` - a built-in helper always returning true, meaning that the policy applies to every request. Within this policy we have a single policy check, declared with `authorize_if`. Checks logically apply from top to bottom, based on their check type. In this case, we'd read the policy as "this policy always applies, and authorizes always". There are four check types, all of which do what they sound like they do: - `authorize_if` - if the check is true, the whole policy is authorized. - `authorize_unless` - if the check is false, the whole policy is authorized. - `forbid_if` - if the check is true, the whole policy is forbidden. - `forbid_unless` - if the check is false, the whole policy is forbidden. If a single check does not explicitly authorize or forbid the whole policy, then the flow moves to the next check. For example, if an `authorize_if` check does NOT return true, this *does not mean the whole policy is forbidden* - it means that further checking is required. ### [](policies.html#policy-with-condition-inside-do-block)Policy with `condition` inside `do` block A condition or a list of conditions can also be moved inside the `policy` block. This can make a really long list of conditions easier to read. ``` policies do policy do condition always() authorize_if always() end end ``` ### [](policies.html#how-a-decision-is-reached)How a Decision is Reached **Not every check in a policy must pass!** This is described above, but is very important so another example is provided here. Checks go from top to bottom, are evaluated independently of each other, and *the first one that reaches a decision* determines the overall *policy result*. For example: ``` policy action_type(:create) do authorize_if IsSuperUser forbid_if Deactivated authorize_if IsAdminUser forbid_if RegularUserCanCreate authorize_if RegularUserAuthorized end ``` We check those from top to bottom, so the first one of those that returns `:authorized` or `:forbidden` determines the entire outcome. For example: ``` authorize_if IsSuperUser # If this is true, the actor is a superuser # None of the rest of the checks matter, even if the actor is deactivated. forbid_if Deactivated authorize_if IsAdminUser forbid_if RegularUserCanCreate authorize_if RegularUserAuthorized ``` Conversely: ``` authorize_if IsSuperUser # This can be false forbid_if Deactivated # This can be false authorize_if IsAdminUser # If this is true, then the policy is still authorized. # And none of these checks matter forbid_if RegularUserCanCreate authorize_if RegularUserAuthorized ``` ### [](policies.html#not-all-policy-checks-have-yes-no-answers)Not all policy checks have yes/no answers This will be covered in greater detail in [Checks](policies.html#checks), but will be briefly mentioned here. Ash provides two basic types of policy checks - *simple* checks and *filter* checks. Simple checks are what we commonly think of with authorization, and what the above example would suggest - is an actor allowed to perform a given operation, yes or no? But we can also use filter checks - given a list of resources, which ones is an actor allowed to perform the operation on? Filter checks are applied to all read actions, including those generated for bulk updates and destroys. ### [](policies.html#bypass-policies)Bypass policies A bypass policy is just like a regular policy, except if a bypass passes, then other policies after it *do not need to pass*. This can be useful for writing complex access rules, or for a simple rule like "an admin can do anything" without needing to specify it as part of every other policy. ### [](policies.html#a-realistic-policy)A realistic policy In this example, we use some of the provided built-in checks. ``` policies do # Anything you can use in a condition, you can use in a check, and vice-versa # This policy applies if the actor is a super_user # Additionally, this policy is declared as a `bypass`. That means that this check is allowed to fail without # failing the whole request, and that if this check *passes*, the entire request passes. bypass actor_attribute_equals(:super_user, true) do authorize_if always() end # This will likely be a common occurrence. Specifically, policies that apply to all read actions policy action_type(:read) do # unless the actor is an active user, forbid forbid_unless actor_attribute_equals(:active, true) # if the record is marked as public, authorize authorize_if expr(public == true) # if the actor is related to the data via that data's `owner` relationship, authorize authorize_if relates_to_actor_via(:owner) end end ``` ## [](policies.html#policy-groups)Policy Groups Policy groups are a small abstraction over policies, that allow you to group policies together that have shared conditions. Each policy inside of a policy group have the same conditions as their group. ``` policies do policy_group actor_attribute_equals(:role, :owner) do policy action_type(:read) do authorize_if expr(owner_id == ^actor(:id)) end policy action_type([:create, :update, :destroy]) do authorize_if expr(owner_id == ^actor(:id)) end end end ``` ### [](policies.html#nesting-policy-groups)Nesting Policy groups Policy groups can be nested. This can help when you have lots of policies and conditions. ``` policies do policy_group condition do policy_group condition2 do policy condition3 do # This policy applies if condition, condition2, and condition3 are all true end end end end ``` ### [](policies.html#bypasses)Bypasses Policy groups can *not* contain bypass policies. The purpose of policy groups is to make it easier to reason about the behavior of policies. When you see a policy group, you know that no policies inside that group will interact with policies in other policy groups, unless they also apply. ### [](policies.html#access-type)Access Type Policies have an "access type" that determines when they are applied. By default, `access_type` is `:filter`. When applied to a read action, `:filter` will result in a filtered read. For other action types, the filter will be evaluated to determine if a forbidden error should be raised. There are three access types, and they determine the *latest point in the process* that any check contained by a policy can be applied. - `strict` - All checks must be applied statically. These result in a forbidden error if they are not met. - `filter` - All checks must be applied either statically or as a filter. These result in a filtered read if they are not met, and a forbidden error for other action types. - `runtime` - This allows checks to be run *after* the data has been read. It is exceedingly rare that you would need to use this access type. For example, given this policy: ``` policy action(:read_hidden) do authorize_if actor_attribute_equals(:is_admin, true) end ``` A non-admin using the `:read_hidden` action would see an empty list of records, rather than a forbidden error. However, with this policy ``` policy action(:read_hidden) do access_type :strict authorize_if actor_attribute_equals(:is_admin, true) end ``` A non-admin using the `:read_hidden` action would see a forbidden error. ### [](policies.html#relationships-and-policies)Relationships and Policies A common point of confusion when working with relationships is when they return less results or no results due to policies. Additionally, when requesting related data that produces a forbidden error, it forbids the *entire request*. For example, if you have a `Post`, that `belongs_to` `:author`, and the user requesting data cannot see the `author` due to a **filter** policy, then you may see something like this: ``` %MyApp.Post{author: nil, ...} ``` Even though it is not possible for a `Post` to exist without an associated `:author`! Additionally, if the user cannot read the `author` due to a `:strict` policy, if you attempt to load the `:author`, the result of the **entire operation** will be `{:error, %Ash.Error.Forbidden{}}`. There are two ways that you can improve this behavior #### The `allow_forbidden_field?` Option This option will **default to `true`** in 4.0. You can adopt this behavior now with the following configuration. ``` config :ash, :allow_forbidden_field_for_relationships_by_default, true ``` This option adjusts the relationship reading logic such that, if running a related read action would produce a forbidden error, the relationship will be set to `%Ash.ForbiddenField{}`, instead of forbidding the entire request. So in the example above where the **entire operation** fails, you would instead get: ``` {:ok, %MyApp.Post{author: %Ash.ForbiddenField{}}} ``` #### The `authorize_read_with` Option This option typically only makes sense to apply on `has_one` and `belongs_to` relationships. This alters the behavior of policy filtering when loading related records. In our above example, lets say there is a policy like the following on `MyApp.Author`, that prevents us from reading an author that has been deactivated. ``` policy action_type(:read) do access_type :filter # This is the default access type. It is here for example. authorize_if expr(active == false) end ``` When running a normal read action against that resource, you want any deactivated authors to be filtered out. However, when reading the `:author` relationship, you don't want the author to appear as `nil`. This is especially useful when combined with `allow_forbidden_field? true`. So lets make our `belongs_to` relationship looks like this. ``` belongs_to :author, MyApp.Author do allow_nil? false allow_forbidden_field? true athorize_read_with :error end ``` Now, that filter will be applied in such a way that produces an error if any record exists that matches `not(active == false)`. So a forbidden read of the `:author` relationship will never produce a `nil` value, nor will it produce an `{:error, %Ash.Error.Forbidden{}}` result. Instead, it the value of `:author` will be `%Ash.ForbiddenField{}`! ## [](policies.html#checks)Checks Checks evaluate from top to bottom within a policy. A check can produce one of three results, the same that a policy can produce. While checks are not necessarily evaluated in order, they *logically apply* in that order, so you may as well think of it in that way. It can be thought of as a step-through algorithm. For each check, starting from the top: - Run the check. - If it returns `:authorized`, the policy is `:authorized` - If it returns `:forbidden`, the policy is `:forbidden` - If it returns `:unknown`, the next check down is checked For the example from earlier: - `authorize_if IsSuperUser` - If this check succeeds, it returns `:authorized`, the whole policy is `:authorized`, and checks stop running - If this check fails, it returns `:unknown` and the next check is checked - `forbid_if Deactivated` - We only care about this result if the previous check failed, ie. the actor is not a super user. - If this check succeeds, it returns `:forbidden`, the whole policy is `:forbidden`, and checks stop running - If this check fails, it returns `:unknown` and the next check is checked - `authorize_if IsAdminUser` - We only care about this result if the previous checks failed, ie. the actor is not a super user and is not deactivated. - If this check succeeds, it returns `:authorized`, the whole policy is `:authorized` and checks stop running. - If this check fails, it returns `:unknown` and the next check is checked - `authorize_if RegularUserAuthorized` - We only care about this result if the previous checks failed, ie. the actor is not a super user, not deactivated and not an admin user. - If this check succeeds, it returns `:authorized`, the whole policy is `:authorized` and checks stop running. - If this check fails, it returns `:unknown`. As there are no more checks to run, the whole policy returns `:unknown`, which is treated as forbidden and the actor is not allowed to perform the action. ### [](policies.html#types-of-checks)Types of checks As mentioned earlier, there are two distinct types of checks - *simple* checks and *filter* checks. So far we've seen examples of both - let's look in a bit more detail. #### Manual Checks Both simple and filter checks are a subset of a third type of check - a *manual* check - but you will almost always want to write simple or filter checks. #### Simple checks Simple checks are determined at the outset of a request, and can only cause a request to be authorized or forbidden. These are typically yes/no questions - is the actor an admin? Did the actor create the post they want to call the `update` action on? Is the actor old enough to drink alcohol? You can write a simple check by creating a new module and using the [`Ash.Policy.SimpleCheck`](Ash.Policy.SimpleCheck.html) module: ``` defmodule MyApp.Checks.ActorIsOldEnough do use Ash.Policy.SimpleCheck # This is used when logging a breakdown of how a policy is applied - see Logging below. def describe(_) do "actor is old enough" end # The context here may have a changeset, query, resource, and domain module, depending # on the action being run. # `match?` should return true or false, and answer the statement being posed in the description, # i.e "is the actor old enough?" def match?(%MyApp.User{age: age} = _actor, %{resource: MyApp.Beer} = _context, _opts) do age >= 21 end def match?(_, _, _), do: false end ``` You can then use this module as the check name, as part of a policy: ``` defmodule MyApp.Beer do # ... policies do policy action(:drink) do authorize_if MyApp.Checks.ActorIsOldEnough end end # ... end ``` Ash will internally convert the true/false return value from `match?/3` to a `:authorized`/`:forbidden`/`:unknown` response, depending on how the check is being run (ie. whether it's part of an `authorize_if`/`forbid_if`/etc.) #### Filter checks Many checks won't return a status yes/no, but instead return a "filter" to apply to a collection of data. They are most commonly used for read actions, but can be used for all types of actions. For update and destroy actions, they apply to the data *before* the action is run. For read actions, they will automatically restrict the returned data to be compliant with the filter. Using the drinking example from earlier, we could write a filter check to list only users that are old enough to drink alcohol. There are two ways to write a filter check - by creating a module and using the [`Ash.Policy.FilterCheck`](Ash.Policy.FilterCheck.html) module, or by using inline expression syntax. ``` defmodule MyApp.Checks.ActorOverAgeLimit do use Ash.Policy.FilterCheck # A description is not necessary, as it will be derived from the filter, but one could be added # def describe(_opts), do: "actor is over the age limit" def filter(_options, _authorizer, _opts) do expr(age_limit <= ^actor(:age)) end end ``` You can then use this module as the check name, as part of a policy: ``` defmodule MyApp.User do # ... policies do policy action(:of_drinking_age) do authorize_if MyApp.Checks.ActorOverAgeLimit end end # ... end ``` #### Inline checks Inline checks are filter checks, but are different enough to warrant their own documentation. These are written directly in a policy, eg. ``` policy action_type(:read) do # Allow records with the attribute `public` set to true to be read authorize_if expr(public == true) # Allow records with the attribute `level` less than the value of the `level` # argument to the action to be read authorize_if expr(level <= ^arg(:level)) end ``` ##### Inline checks for create actions When using expressions inside of policies that apply to create actions, you may not reference the data being created. For example: ``` policy action_type(:create) do # This check is fine, as we only reference the actor authorize_if expr(^actor(:admin) == true) # This check is not, because it contains a reference to a field authorize_if expr(status == :active) end ``` ### [](policies.html#why-can-t-we-reference-data-in-creates)Why can't we reference data in creates? We cannot allow references to the data being created in create policies, because we do not yet know what the result of the action will be. For updates and destroys, referencing the data always references the data *prior* to the action being run, and so it is deterministic. If a policy that applies to creates, would result in a filter, you will get a [`Ash.Error.Forbidden.CannotFilterCreates`](Ash.Error.Forbidden.CannotFilterCreates.html) at runtime explaining that you must change your check. Typically this means writing a custom [`Ash.Policy.SimpleCheck`](Ash.Policy.SimpleCheck.html) instead. Ash also comes with a set of built-in helpers for writing inline checks - see [`Ash.Policy.Check.Builtins`](Ash.Policy.Check.Builtins.html) for more information. ##### Referencing the actor In expression checks, the `actor` template can be used (other templates that may work in filter expressions, for example, are not available). For example: ``` # Authorize records that have an author relationship with the author ID the same as the actor ID # ie. records authored by the actor authorize_if expr(author.id == ^actor(:id)) ``` ##### Using `exists` A common mistake when using related data in filters is to be too restrictive. Imagine a scenario where you have an action like this: ``` read :friends_of_ted do filter expr(friends.first_name == "ted") end ``` If this was in a User resource, it would return users that have a friend with the first name "ted". So far so good. Then someone calls it like so: ``` Resource |> Ash.Query.for_read(:friends_of_ted) |> Ash.Query.filter(friends.last_name == "dansen") ``` The resulting filter is `friends.first_name == "ted" and friends.last_name == "dansen"`- this means that you'll get users that have a friend with the full name "ted dansen". That *might* be what you meant, but more likely you would want "users that have a friend with the first name "ted", that also have a friend with the last name 'dansen'". To accomplish that, we can use the `exists` helper and rework the example like so: ``` # There exists a friend with the first name "ted" read :friends_of_ted do filter expr(exists(friends, first_name == "ted")) end # And there also exists a friend with the last name "dansen" # They may be the same friend if the user is friends with Ted Dansen! Resource |> Ash.Query.for_read(:friends_of_ted) |> Ash.Query.filter(exists(friends, last_name == "dansen")) ``` In policies (and often any time you mean "a related thing exists where some condition is true"), it is advised to use `exists/2` when referring to relationships because of the way that the policy authorizer may mix &amp; match your policies when building filters. This is also true when adding filters to actions. If you use `exists`, then your policies can be used in filters without excluding unnecessary data. ## [](policies.html#field-policies)Field Policies Field policies allow you to authorize access to specific fields via policies scoped to fields. For example: ``` field_policies do field_policy :role do authorize_if actor_attribute_equals(:role, :supervisor) end end ``` If *any* field policies exist then *all* fields must be authorized by a field policy. If you want a "deny-list" style, then you can add policies for specific fields. and add a catch-all policy using the special field name `:*`. All policies that apply to a field must be authorized. The only exception to the above behavior is primary keys, which can always be read by everyone. Additionally, keep in mind that adding [`Ash.Policy.Authorizer`](Ash.Policy.Authorizer.html) will require that all actions pass policies. If you want to just add field policies, you will need to add a policy that allows all access explicitly, i.e ``` policies do policy always() do authorize_if always() end end ``` ### [](policies.html#using-expressions-in-field-policies)Using Expressions In Field Policies Unlike in regular policies, expressions in field policies cannot refer to related entities currently (except when using exists). Instead, you will need to create aggregates or expression calculations that return the results you want to reference. In results, forbidden fields will be replaced with a special value: `%Ash.ForbiddenField{}`. When these fields are referred to in filters, they will be replaced with an expression that evaluates to `nil`. To support this behavior, only simple and filter checks are allowed in field policies. ### [](policies.html#handling-private-fields-in-internal-functions)Handling private fields in internal functions When calling internal functions like [`Ash.read!/1`](Ash.html#read!/1), private fields will by default always be shown. Even if field policies apply to the resource. You can change the default behaviour by setting the `private_fields` option on field policies. ``` field_policies do private_fields :include end ``` The different options are: - `:show` will always show private fields - `:hide` will always hide private fields - `:include` will let you to write field policies for private fields and private fields will be shown or hidden depending on the outcome of the policy If you want to overwrite the default option that is `:show`, you can do that by setting a global flag: ``` config :ash, :policies, private_fields: :include ``` ## [](policies.html#debugging-and-logging)Debugging and Logging ### [](policies.html#policy-breakdowns)Policy Breakdowns Policy breakdowns can be fetched on demand for a given forbidden error (either an [`Ash.Error.Forbidden`](Ash.Error.Forbidden.html) that contains one ore more [`Ash.Error.Forbidden.Policy`](Ash.Error.Forbidden.Policy.html) errors, or an [`Ash.Error.Forbidden.Policy`](Ash.Error.Forbidden.Policy.html) error itself), via [`Ash.Error.Forbidden.Policy.report/2`](Ash.Error.Forbidden.Policy.html#report/2). Additionally, you can request that they be provided in the error message for all raised forbidden errors (without the help text), by setting ``` config :ash, :policies, show_policy_breakdowns?: true ``` Here is an example policy breakdown from tests. ``` Policy Breakdown A check status of `?` implies that the solver did not need to determine that check. Some checks may look like they failed when in reality there was no need to check them. Look for policies with `✘` and `✓` in check statuses. A check with a `⬇` means that it didn't determine if the policy was authorized or forbidden, and so moved on to the next check. `🌟` and `⛔` mean that the check was responsible for producing an authorized or forbidden (respectively) status. If no check results in a status (they all have `⬇`) then the policy is assumed to have failed. In some cases, however, the policy may have just been ignored, as described above. Admins and managers can create posts | ⛔: authorize if: actor.admin == true | ✘ | ⬇ authorize if: actor.manager == true | ✘ | ⬇ ``` To remove the help text, you can pass the `help_text?: false` option, which would leave you with: ``` Policy Breakdown Admins and managers can create posts | ⛔: authorize if: actor.admin == true | ✘ | ⬇ authorize if: actor.manager == true | ✘ | ⬇ ``` ### [](policies.html#including-in-error-messages)Including in error messages **IMPORTANT WARNING:** The following configuration should only ever be used in development mode! For security reasons, authorization errors don't include any extra information, aside from `forbidden`. To have authorization errors include a policy breakdown (without help text) use the following config. ``` config :ash, :policies, show_policy_breakdowns?: true ``` ### [](policies.html#logging)Logging It is generally safe to log authorization error details, even in production. This can be very helpful when investigating certain classes of issue. To have Ash automatically log each authorization failure, use ``` config :ash, :policies, log_policy_breakdowns: :error # Use whatever log level you'd like to use here ``` To have Ash log all policy breakdowns, even successful ones (this will be lots of noise, and should only be used for dev testing) ``` config :ash, :policies, log_successful_policy_breakdowns: :error # Use whatever log level you'd like to use here ``` [← Previous Page Sensitive Data](sensitive-data.html) [Next Page → Project Structure](project-structure.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/security/policies.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Define Polymorphic Relationships [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/how-to/polymorphic-relationships.livemd#L1 "View Source") [![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](polymorphic-relationships.html) ``` Mix.install([{:ash, "~> 3.0"}], consolidate_protocols: false) ``` ``` :ok ``` ## [](polymorphic-relationships.html#introduction)Introduction Something that comes up in more complex domains is the idea of "polymorphic relationships". For this example, we will use the concept of a `BankAccount`, which can be either a `SavingsAccount` or a `CheckingAccount`. All accounts have an `account_number` and `transactions`, but checkings &amp; savings accounts might have their own specific information. For example, a `SavingsAccount` has an `interest_rate`, and a `CheckingAccount` has many `debit_card`s. Ash does not support polymorphic relationships defined *as relationships*, but you can accomplish similar functionality via [calculations](calculations.html) with the type [`Ash.Type.Union`](Ash.Type.Union.html). For this tutorial, we will have a dedicated resource called `BankAccount`. I suggest taking that approach, as many things down the road will be simplified. With that said, you don't necessarily need to do that when there is no commonalities between the types. Instead of setting up the polymorphism on the `BankAccount` resource, you would define relationships to `SavingsAccount` and `CheckingAccount` directly. This tutorial is not attempting to illustrate good design of accounting systems. We make many concessions for the sake of the simplicity of our example. ## [](polymorphic-relationships.html#defining-our-resources)Defining our Resources ``` defmodule BankAccount do use Ash.Resource, domain: Finance, data_layer: Ash.DataLayer.Ets actions do defaults [:read, :destroy, create: [:account_number, :type]] end attributes do uuid_primary_key :id attribute :account_number, :integer, allow_nil?: false attribute :type, :atom, constraints: [one_of: [:checking, :savings]] end # calculations do # calculate :implementation, AccountImplementation, GetAccountImplementation do # allow_nil? false # end # end relationships do has_one :checking_account, CheckingAccount has_one :savings_account, SavingsAccount end end defmodule CheckingAccount do use Ash.Resource, domain: Finance, data_layer: Ash.DataLayer.Ets actions do defaults [:read, :destroy, create: [:bank_account_id]] end attributes do uuid_primary_key :id end identities do identity :unique_bank_account, [:bank_account_id], pre_check?: true end relationships do belongs_to :bank_account, BankAccount do allow_nil? false end end end defmodule SavingsAccount do use Ash.Resource, domain: Finance, data_layer: Ash.DataLayer.Ets actions do defaults [:read, :destroy, create: [:bank_account_id]] end attributes do uuid_primary_key :id end identities do identity :unique_bank_account, [:bank_account_id], pre_check?: true end relationships do belongs_to :bank_account, BankAccount do allow_nil? false end end end defmodule Finance do use Ash.Domain, validate_config_inclusion?: false resources do resource BankAccount resource SavingsAccount resource CheckingAccount end end ``` ``` {:module, Finance, <<70, 79, 82, 49, 0, 0, 44, ...>>, [ Ash.Domain.Dsl.Resources.Resource, Ash.Domain.Dsl.Resources.Options, %{opts: [], entities: [%Ash.Domain.Dsl.ResourceReference{...}, ...]} ]} ``` We haven't implemented the polymorphic part yet, but lets create a few of the above resources to show how they relate. Below we create a `BankAccount` for checkings, and a `BankAccount` for savings, and connect them to their "specific" types, i.e `CheckingAccount` and `SavingsAccount`. We load the data, you can see that one `BankAccount` has a `:checking_account` but no `:savings_account`. For the other, the opposite is the case. ``` bank_account1 = Ash.create!(BankAccount, %{account_number: 1, type: :checking}) bank_account2 = Ash.create!(BankAccount, %{account_number: 2, type: :savings}) checking_account = Ash.create!(CheckingAccount, %{bank_account_id: bank_account1.id}) savings_account = Ash.create!(SavingsAccount, %{bank_account_id: bank_account2.id}) [bank_account1, bank_account2] |> Ash.load!([:checking_account, :savings_account]) ``` ``` [ #BankAccount< implementation: #Ash.NotLoaded<:calculation, field: :implementation>, savings_account: nil, checking_account: #CheckingAccount< bank_account: #Ash.NotLoaded<:relationship, field: :bank_account>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "60f585f6-f352-410e-8c09-09ae49448851", bank_account_id: "21d27a6c-49b8-4984-a1b7-f2ef030626af", aggregates: %{}, calculations: %{}, ... >, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "21d27a6c-49b8-4984-a1b7-f2ef030626af", account_number: 1, type: :checking, aggregates: %{}, calculations: %{}, ... >, #BankAccount< implementation: #Ash.NotLoaded<:calculation, field: :implementation>, savings_account: #SavingsAccount< bank_account: #Ash.NotLoaded<:relationship, field: :bank_account>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "d2bcc1cc-d709-418d-a9ff-0d21fd7d667b", bank_account_id: "4d8dc988-3e09-4efb-a643-d822013abfba", aggregates: %{}, calculations: %{}, ... >, checking_account: nil, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "4d8dc988-3e09-4efb-a643-d822013abfba", account_number: 2, type: :savings, aggregates: %{}, calculations: %{}, ... > ] ``` ## [](polymorphic-relationships.html#defining-our-union-type)Defining our union type Below we define an [`Ash.Type.NewType`](Ash.Type.NewType.html). This allows defining a new type that is the combination of an existing type and custom constraints. ``` defmodule AccountImplementation do use Ash.Type.NewType, subtype_of: :union, constraints: [ types: [ checking: [ type: :struct, constraints: [instance_of: CheckingAccount] ], savings: [ type: :struct, constraints: [instance_of: SavingsAccount] ] ] ] end ``` ``` {:module, AccountImplementation, <<70, 79, 82, 49, 0, 0, 44, ...>>, :ok} ``` ## [](polymorphic-relationships.html#defining-the-calculation)Defining the calculation Next, we'll define a calculation resolves to the specific type of any given account. ``` defmodule GetAccountImplementation do use Ash.Resource.Calculation def load(_, _, _) do [:checking_account, :savings_account] end def calculate(records, _, _) do Enum.map(records, &(&1.checking_account || &1.savings_account)) end end ``` ``` {:module, GetAccountImplementation, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:calculate, 3}} ``` ## [](polymorphic-relationships.html#adding-the-calculation-to-our-resource)Adding the calculation to our resource Finally, we'll add the calculation to our `BankAccount` resource! For those following along with the LiveBook, go back up and uncomment the commented out calculation. Now we can load `:implementation` and see that, for one account, it resolves to a `CheckingAccount` and for the other it resolves to a `SavingsAccount`. ``` bank_account1 = Ash.create!(BankAccount, %{account_number: 1, type: :checking}) bank_account2 = Ash.create!(BankAccount, %{account_number: 2, type: :savings}) checking_account = Ash.create!(CheckingAccount, %{bank_account_id: bank_account1.id}) savings_account = Ash.create!(SavingsAccount, %{bank_account_id: bank_account2.id}) [bank_account1, bank_account2] |> Ash.load!([:implementation]) ``` ``` [ #BankAccount< implementation: #CheckingAccount< bank_account: #Ash.NotLoaded<:relationship, field: :bank_account>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "1d1a7b6c-dd08-4b8c-9769-2c1155a41a40", bank_account_id: "ce370381-303e-49dc-9950-a05b5052e7f8", aggregates: %{}, calculations: %{}, ... >, savings_account: #Ash.NotLoaded<:relationship, field: :savings_account>, checking_account: #Ash.NotLoaded<:relationship, field: :checking_account>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "ce370381-303e-49dc-9950-a05b5052e7f8", account_number: 1, type: :checking, aggregates: %{}, calculations: %{}, ... >, #BankAccount< implementation: #SavingsAccount< bank_account: #Ash.NotLoaded<:relationship, field: :bank_account>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "e537116d-c5b8-414a-a350-fa9b2afe0a4e", bank_account_id: "c4739158-2a1f-4de8-bccb-ee1d1ee9e602", aggregates: %{}, calculations: %{}, ... >, savings_account: #Ash.NotLoaded<:relationship, field: :savings_account>, checking_account: #Ash.NotLoaded<:relationship, field: :checking_account>, __meta__: #Ecto.Schema.Metadata<:loaded>, id: "c4739158-2a1f-4de8-bccb-ee1d1ee9e602", account_number: 2, type: :savings, aggregates: %{}, calculations: %{}, ... > ] ``` ## [](polymorphic-relationships.html#taking-it-further)Taking it further One of the best things about using [`Ash.Type.Union`](Ash.Type.Union.html) is how it is *integrated*. Every extension (provided by the Ash team) supports working with unions. For example: - [Working with Unions in AshPhoenix.Form](../ash_phoenix/union-forms.html) - [AshGraphql &amp; AshJsonApi Unions](../ash_graphql/use-unions-with-graphql.html) You can also synthesize filterable fields with calculations. For example, if you wanted to allow filtering `BankAccount` by `:interest_rate`, and that field only existed on `SavingsAccount`, you might have a calculation like this on `BankAccount`: ``` calculate :interest_rate, :decimal, expr( if type == :savings do savings_account.interest_rate else 0 end ) ``` This would allow usage like the following: ``` BankAccount |> Ash.Query.filter(interest_rate > 0.01) |> Ash.read!() ``` [← Previous Page Writing Extensions](writing-extensions.html) [Next Page → Test Resources](test-resources.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/how-to/polymorphic-relationships.livemd)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Preparations [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/preparations.md#L1 "View Source") Preparations are the primary way of customizing read action behavior. If you are familiar with [`Plug`](../plug/1.16.1/Plug.html), you can think of an [`Ash.Resource.Preparation`](Ash.Resource.Preparation.html) as the equivalent of a [`Plug`](../plug/1.16.1/Plug.html) for queries. At its most basic, a preparation will take a query and return a new query. Queries can be simple, like adding a filter or a sort, or more complex, attaching hooks to be executed within the lifecycle of the action. ## [](preparations.html#builtin-preparations)Builtin Preparations There are builtin preparations that can be used, and are automatically imported into your resources. See [`Ash.Resource.Preparation.Builtins`](Ash.Resource.Preparation.Builtins.html) for more. The primary preparation you will use is `build/1`, which passes the arguments through to [`Ash.Query.build/2`](Ash.Query.html#build/2) when the preparation is run. See that function for what options can be provided. Some examples of usage of builtin preparations ``` # sort by inserted at descending prepare build(sort: [inserted_at: :desc]) # only show the top 5 results prepare build(sort: [total_points: :desc], limit: 5) ``` ## [](preparations.html#custom-preparations)Custom Preparations ``` defmodule MyApp.Preparations.Top5 do use Ash.Resource.Preparation # transform and validate opts @impl true def init(opts) do if is_atom(opts[:attribute]) do {:ok, opts} else {:error, "attribute must be an atom!"} end end @impl true def prepare(query, opts, _context) do attribute = opts[:attribute] query |> Ash.Query.sort([{attribute, :desc}]) |> Ash.Query.limit(5) end end ``` This could then be used in a resource via: ``` prepare {MyApp.Preparations.Top5, attribute: :foo} ``` ## [](preparations.html#anonymous-function-queries)Anonymous Function Queries You can also use anonymous functions for preparations. This is great for prototyping, but we generally recommend using a module for organizational purposes. ``` prepare fn query, _context -> # put your code here end ``` ## [](preparations.html#action-vs-global-preparations)Action vs Global Preparations You can place a preparation on a read action, like so: ``` actions do read :read do prepare {Top5, attribute: :name} end end ``` Or you can use the global preparations block to apply to all read actions. ``` preparations do prepare {Top5, attribute: :name} end ``` The preparations section allows you to add preparations across multiple actions of a resource. [← Previous Page Changes](changes.html) [Next Page → Code Interface](code-interfaces.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/preparations.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Prevent concurrent writes [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/how-to/prevent-concurrent-writes.livemd#L1 "View Source") [![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](prevent-concurrent-writes.html) ``` Mix.install([{:ash, "~> 3.0"}], consolidate_protocols: false) # Set to `:debug` if you want to see ETS logs Logger.configure(level: :warning) ``` ## [](prevent-concurrent-writes.html#introduction)Introduction Often, when working with resources, we want to ensure that a record has not been edited since we last read it. We may want this for UX reasons, or for ensuring data consistency, etc. To ensure that a record hasn't been updated since the last time we read it, we use Optimistic Locking. For more information, see the documentation for [`Ash.Resource.Change.OptimisticLock`](Ash.Resource.Change.OptimisticLock.html). ## [](prevent-concurrent-writes.html#add-optimistic-locking)Add Optimistic Locking 1. Add a `:version` attribute to your resource, of type `:integer`, with a default of `1` and `allow_nil?: false` 2. Add `change optimistic_lock(:version)`. Where you add it depends on which actions you want to prevent concurrent writes for: - If you want optimistic locking to occur for *specific actions*: 1. Add `change optimistic_lock(:version)` to those specific actions - If you want optimistic locking to occur for *all action types*: 1. Add a global `changes` block to the resource, if you do not have one 2. Add `change optimistic_lock(:version), on: [:create, :update, :destroy]` - If you want to apply optimistic locking to *many but not all actions*: 1. Add a global `changes` block to the resource, if you do not have one 2. Add `change optimistic_lock(:version), where: action_is([:action1, :action2, :action3])` ## [](prevent-concurrent-writes.html#examples)Examples ``` defmodule Address do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets attributes do uuid_primary_key :id attribute :version, :integer, allow_nil?: false, default: 1 attribute :state, :string, allow_nil?: false attribute :county, :string, allow_nil?: false end actions do defaults [:read, create: [:state, :county]] update :update do accept [:state, :county] change optimistic_lock(:version) end end # apply to all actions # changes do # change optimistic_lock(:version), on: [:create, :update, :destroy] # end # apply to a list of actions # changes do # change optimistic_lock(:version), where: action_is([:action1, :action2, :action3]) # end end defmodule Domain do use Ash.Domain, validate_config_inclusion?: false resources do resource Address do define(:get_address, action: :read, get_by: [:id]) define(:create_address, action: :create, args: [:state, :county]) define(:update_address, action: :update) end end end ``` ``` {:module, Domain, <<70, 79, 82, 49, 0, 2, 1, ...>>, [ Ash.Domain.Dsl.Resources.Resource, Ash.Domain.Dsl.Resources.Options, Ash.Domain.Dsl, %{opts: [], entities: [...]}, Ash.Domain.Dsl, Ash.Domain.Dsl.Resources.Options, ... ]} ``` ## [](prevent-concurrent-writes.html#triggering-a-stalerecord-error)Triggering a StaleRecord error ``` address = Domain.create_address!("FL", "Pinellas") Domain.update_address!(address, %{state: "NC", county: "Guilford"}) # `address` still has a version of `1`, so our optimistic lock should catch it! Domain.update_address(address, %{county: "Miami-Dade"}) ``` ``` {:error, %Ash.Error.Invalid{ changeset: "#Changeset<>", errors: [ %Ash.Error.Changes.StaleRecord{ resource: "Address", filter: %{"version" => 1}, splode: Ash.Error, bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :invalid } ] }} ``` ## [](prevent-concurrent-writes.html#refetching-a-record-to-get-the-latest-version)Refetching a record to get the latest version ``` address = Domain.create_address!("FL", "Pinellas") Domain.update_address!(address, %{state: "NC", county: "Guilford"}) case Domain.update_address(address, %{county: "Miami-Dade"}) do {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Changes.StaleRecord{}]}} -> # In a liveview, you wouldn't just refetch and resubmit # you would show the user an error and have them submit the form again address = Domain.get_address!(address.id) Domain.update_address!(address, %{county: "Miami-Dade"}) {:ok, domain} -> domain end ``` ``` #Address< __meta__: #Ecto.Schema.Metadata<:loaded>, id: "91e552e1-3307-4d68-969f-1b7e6651e695", version: 3, state: "NC", county: "Miami-Dade", aggregates: %{}, calculations: %{}, ... > ``` [← Previous Page Encrypt Attributes](encrypt-attributes.html) [Next Page → Wrap External APIs](wrap-external-apis.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/how-to/prevent-concurrent-writes.livemd)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Project Structure [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/development/project-structure.md#L1 "View Source") In this guide we'll discuss some best practices for how to structure your project. These recommendations align well with [Elixir conventions](../elixir/1.16.2/naming-conventions.html#casing) around file and module naming. These conventions allow for a logical coupling of module and file names, and help keep your project organized and easy to navigate. ### [](project-structure.html#these-are-recommendations)These are recommendations None of the things we show you here are *requirements*, only recommendations. Feel free to plot your own course here. Ash avoids any pattern that requires you to name a file or module in a specific way, or put them in a specific place. This ensures that all connections between one module and another module are *explicit* rather than *implicit*. These recommendations all correspond to standard practice in most Elixir/Phoenix applications ``` lib/ ├── my_app/ # Your application's main namespace │ ├── accounts.ex # Accounts domain module │ ├── helpdesk.ex # Helpdesk domain module │ │ │ ├── accounts/ # Accounts context │ │ ├── user.ex # User resource │ │ ├── user/ # User resource files │ │ ├── token.ex # Token resource │ │ └── password_helper.ex # Support module │ │ │ └── helpdesk/ # Helpdesk context │ ├── ticket.ex # Ticket resource │ ├── notification.ex # Notification resource │ ├── other_file.ex # Support module │ └── ticket/ # Ticket resource files │ ├── preparations/ │ ├── changes/ │ └── checks/ ``` Place your Ash application in the standard Elixir application directory `lib/my_app`. Your [`Ash.Domain`](Ash.Domain.html) modules should be at the root level of this directory. Each domain should have a directory named after it, containing the domain's [`Ash.Resource`](Ash.Resource.html) modules and any of the domain's supporting modules. All resource interaction ultimately goes through a domain module. For resources that require additional files, create a dedicated folder in the domain context named after the resource. We suggest organizing these supplementary files into subdirectories by type (like `changes/`, `preparations/`, etc.), though this organization is optional. # Where do I put X thing The purpose of Ash is to be both the model of and the interface to your domain logic (A.K.A business logic). Applying this generally looks like building as much of your domain logic "behind" your resources. This does not mean, however, that everything has to go *inside of* your resources. For example, if you have a `Purchase` resource, and you want to be able to display a list of purchases that were taxable, and also calculate the percentage of the purchase that was taxable. You might have an action called `:taxable` and a calculation called `:percentage_tax`. ## [](project-structure.html#example-1-reads-calculations)Example 1: Reads &amp; Calculations ``` actions do ... read :taxable do filter expr(taxable == true) end end calculations do calculate :percentage_tax, :decimal, expr( sum(line_items, field: :amount, query: [filter: tax == true]) / sum(line_items, field: :amount) ) end ``` In practice, you may not need the `taxable` action, i.e perhaps you simply want a "taxable" checkbox on a list view in your application, in which case you may use the primary read, or some other read like `:transaction_report`. You would then, on the consumer, provide the filter for `taxable == true`, and load the `:percentage_tax` calculation. ## [](project-structure.html#example-2-using-external-data-in-create-actions)Example 2: Using external data in create actions Lets say you want the user to fill in a github issue id, and you will fetch information from that github issue to use as part of creating a "ticket" in your system.. You might be tempted to do something like this in a LiveView: ``` def handle_event("link_ticket", %{"issue_id" => issue_id}, socket) do issue_info = GithubApi.get_issue(issue_id) MyApp.Support.update_ticket(socket.assigns.ticket_id, %{issue_info: %{ title: issue_info.title, body: issue_info.body }}) end ``` But this is putting business logic inside of your UI/representation layer. Instead, you should write an action and put this logic inside of it. ``` defmodule MyApp.Ticket.FetchIssueInfo do use Ash.Resource.Change def change(changeset, _, _) do Ash.Changeset.before_transaction(changeset, fn changeset -> issue_info = GithubApi.get_issue(changeset.arguments.issue_id) Ash.Changeset.force_change_attributes(changeset, %{ issue_info: %{ title: issue_info.title, body: issue_info.body } }) end) end end ``` Then you'd have an action like this: ``` update :link_ticket do argument :issue_id, :string, allow_nil?: false change MyApp.Ticket.FetchIssueInfo end ``` This cleanly encapsulates the operation behind the resource, even while the code for fetching the github issue still lives in a `GitHubApi` module. [← Previous Page Policies](policies.html) [Next Page → Generators](generators.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/development/project-structure.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Reactor [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/advanced/reactor.md#L1 "View Source") [`Ash.Reactor`](Ash.Reactor.html) is an extension for [`Reactor`](https://github.com/ash-project/reactor) which adds explicit support for interacting with resources via their defined actions. See [Getting started with Reactor](../reactor/getting-started-with-reactor.html) for more information about Reactor. ## [](reactor.html#usage)Usage You can either add the [`Ash.Reactor`](Ash.Reactor.html) extension to your existing reactors eg: ``` defmodule MyExistingReactor do use Reactor, extensions: [Ash.Reactor] end ``` or for your convenience you can use `use Ash.Reactor` which expands to exactly the same as above. ## [](reactor.html#example)Example An example is worth 1000 words of prose: ``` defmodule ExampleReactor do use Ash.Reactor ash do default_domain ExampleDomain end input :customer_name input :customer_email input :plan_name input :payment_nonce create :create_customer, Customer do inputs %{name: input(:customer_name), email: input(:customer_email)} end read_one :get_plan, Plan, :get_plan_by_name do inputs %{name: input(:plan_name)} fail_on_not_found? true end action :take_payment, PaymentProvider do inputs %{ nonce: input(:payment_nonce), amount: result(:get_plan, [:price]) } end create :subscription, Subscription do inputs %{ plan_id: result(:get_plan, [:id]), payment_provider_id: result(:take_payment, :id) } end end ``` ## [](reactor.html#actions)Actions For each action type there is a corresponding step DSL, which needs a name (used to refer to the result of the step by other steps), a resource and optional action name (defaults to the primary action if one is not provided). Actions have several common options and some specific to their particular type. See the [DSL documentation](dsl-ash-reactor.html) for details. ### [](reactor.html#action-inputs)Action inputs Ash actions take a map of input parameters which are usually a combination of resource attributes and action arguments. You can provide these values as a single map using the [`inputs` DSL entity](dsl-ash-reactor.html#reactor-action-inputs) with a map or keyword list which refers to Reactor inputs, results and hard-coded values via Reactor's [predefined template functions](../reactor/Reactor.Dsl.Argument.html#functions). For action types that act on a specific resource (ie `update` and `destroy`) you can provide the value using the [`initial` DSL option](dsl-ash-reactor.html#reactor-update-initial). #### Example ``` input :blog_title input :blog_body input :author_email read :get_author, MyBlog.Author, :get_author_by_email do inputs %{email: input(:author_email)} end create :create_post, MyBlog.Post, :create do inputs %{ title: input(:blog, [:title]), body: input(:blog, [:body]), author_id: result(:get_author, [:email]) } end update :author_post_count, MyBlog.Author, :update_post_count do wait_for :create_post initial result(:get_author) end return :create_post ``` ## [](reactor.html#handling-failure)Handling failure. Reactor is a saga executor, which means that when failure occurs it tries to clean up any intermediate state left behind. By default the `create`, `update` and `destroy` steps do not specify any behaviour for what to do when there is a failure downstream in the reactor. This can be changed by providing both an `undo_action` and changing the step's `undo` option to either `:outside_transaction` or `:always` depending on your resource and datalayer semantics. ### [](reactor.html#the-undo-option)The `undo` option. - `:never` - this is the default, and means that the reactor will never try and undo the action's work. This is the most performant option, as it means that the reactor doesn't need to store as many intermediate values. - `:outside_transaction` - this option allows the step to decide at runtime whether it should support undo based on whether the action is being run within a transaction. If it is, then no undo is required because the transaction will rollback. - `:always` - this forces the step to always undo it's work on failure. ### [](reactor.html#the-undo_action-option)The `undo_action` option. The behaviour of the `undo_action` is action specific: - For `create` actions, the `undo_action` should be the name of a `destroy` action with no specific requirements. - For `update` actions, the `undo_action` should also be an `update` action which takes a `changeset` argument, which will contain the [`Ash.Changeset`](Ash.Changeset.html) which was used to execute the original update. - For `destroy` actions, the `undo_action` should be the name of a `create` action which takes a `record` argument, which will contain the resource record which was used destroyed. ### [](reactor.html#transactions)Transactions You can use the `transaction` step type to wrap a group of steps inside a data layer transaction, however the following caveats apply: - All steps inside a transaction must happen in the same process, so the steps inside the transaction will only ever be executed synchronously. - Notifications will be sent only when the transaction is committed. ## [](reactor.html#notifications)Notifications Because a reactor has transaction-like semantics notifications are automatically batched and only sent upon successful completion of the reactor. ## [](reactor.html#running-reactors-as-an-action)Running Reactors as an action Ash's [generic actions](actions.html#generic-actions) now support providing a Reactor module directly as their `run` option. Notes: - Every Reactor input must have a corresponding action argument. - Ash's action context is passed in as the Reactor's context (including things like actor, tenant, etc). - [Reactor runtime options](../reactor/0.10.3/Reactor.html#t:options/0) can be set by setting `run {MyReactor, opts}` instead of just `run MyReactor`. - If you set the `transaction?` action DSL option to true then the Reactor will be run synchronously - regardless of the value of the `async?` runtime option. ### [](reactor.html#example-1)Example ``` action :run_reactor, :struct do constraints instance_of: MyBlog.Post argument :blog_title, :string, allow_nil?: false argument :blog_body, :string, allow_nil?: false argument :author_email, :ci_string, allow_nil?: false run MyBlog.CreatePostReactor end ``` [← Previous Page Upgrade](upgrading-to-3-0.html) [Next Page → Monitoring](monitoring.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/advanced/reactor.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Read Actions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/actions/read-actions.md#L1 "View Source") Read actions operate on an [`Ash.Query`](Ash.Query.html). Read actions always return lists of data. The act of [pagination](read-actions.html#pagination), or returning a [single result](read-actions.html#ash-get), is handled as part of the interface, and is not a concern of the action itself. Here is an example of a read action: ``` # Giving your actions informative names is always a good idea read :ticket_queue do # Use arguments to take in values you need to run your read action. argument :priorities, {:array, :atom} do constraints items: [one_of: [:low, :medium, :high]] end # This action may be paginated, # and returns a total count of records by default pagination offset: true, countable: :by_default # Arguments can be used in preparations and filters filter expr(status == :open and priority in ^arg(:priorities)) end ``` For a full list of all of the available options for configuring read actions, see [the Ash.Resource.Dsl documentation](dsl-ash-resource.html#actions-read). ## [](read-actions.html#ash-get)Ash.get! The `Ash.get!` function is a convenience function for running a read action, filtering by a unique identifier, and expecting only a single result. It is equivalent to the following code: ``` Ash.get!(Resource, 1) # is roughly equivalent to Resource |> Ash.Query.filter(id == 1) |> Ash.Query.limit(2) |> Ash.read!() |> case do [] -> # raise not found error [result] -> result [_, _] -> # raise too many results error end ``` ## [](read-actions.html#ash-read_one)Ash.read\_one! The `Ash.read_one!` function is a similar convenience function to `Ash.get!`, but it does not take a unique identifier. It is useful when you expect an action to return only a single result, and want to enforce that and return a single result. ``` Ash.read_one!(query) # is roughly equivalent to query |> Ash.Query.limit(2) |> Ash.read!() |> case do [] -> nil [result] -> result [_, _] -> # raise too many results error end ``` ## [](read-actions.html#pagination)Pagination Ash provides built-in support for pagination when reading resources and their relationships. You can find more information about this in the [pagination guide](pagination.html). ## [](read-actions.html#what-happens-when-you-call-ash-query-for_read-4)What happens when you call Ash.Query.for\_read/4 The following steps are performed when you call [`Ash.Query.for_read/4`](Ash.Query.html#for_read/4). - Cast input arguments - `Ash.Resource.Dsl.actions.read.argument` - Set default argument values - `Ash.Resource.Dsl.actions.read.argument.default` - Add errors for missing required arguments | `Ash.Resource.Dsl.actions.read.argument.allow_nil?` - Run query preparations | `Ash.Resource.Dsl.actions.read.prepare` - Add action filter | `Ash.Resource.Dsl.actions.read.filter` ## [](read-actions.html#what-happens-when-you-run-the-action)What happens when you run the action These steps are trimmed down, and are aimed at helping users understand the general flow. Some steps are omitted. - Run [`Ash.Query.for_read/3`](Ash.Query.html#for_read/3) if it has not already been run - [Apply tenant filters for attribute](multitenancy.html) - Apply [pagination](pagination.html) options - Run before action hooks - Multi-datalayer filter is synthesized. We run queries in other data layers to fetch ids and translate related filters to `(destination_field in ^ids)` - Strict Check &amp; Filter Authorization is run - Data layer query is built and validated - Field policies are added to the query - Data layer query is Run - Authorizer "runtime" checks are run (you likely do not have any of these) The following steps happen while(asynchronously) or after the main data layer query has been run - If paginating and count was requested, the count is determined at the same time as the query is run. - Any calculations &amp; aggregates that were able to be run outside of the main query are run - Relationships, calculations, and aggregates are loaded [← Previous Page Actions](actions.html) [Next Page → Create Actions](create-actions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/actions/read-actions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Home [View Source](https://github.com/ash-project/ash/blob/v3.4.58/README.md#L1 "View Source") ![Logo](https://github.com/ash-project/ash/blob/main/logos/cropped-for-header-black-text.png?raw=true#gh-light-mode-only) ![Logo](https://github.com/ash-project/ash/blob/main/logos/cropped-for-header-white-text.png?raw=true#gh-dark-mode-only) ![Elixir CI](https://github.com/ash-project/ash/workflows/Ash%20CI/badge.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Hex version badge](https://img.shields.io/hexpm/v/ash.svg)](https://hex.pm/packages/ash) [![Hexdocs badge](https://img.shields.io/badge/docs-hexdocs-purple)](../ash.html) # Ash Framework Welcome! Here you will find everything you need to know to get started with and use Ash. This documentation is best viewed on [hexdocs](../ash.html). ## [](readme.html#dive-in)Dive In - [What is Ash?](what-is-ash.html) - [Get Started](get-started.html) - [See the roadmap](https://github.com/orgs/ash-project/projects/3) ## [](readme.html#about-the-documentation)About the Documentation [**Tutorials**](readme.html#tutorials) walk you through a series of steps to accomplish a goal. These are **learning-oriented**, and are a great place for beginners to start. * * * [**Topics**](readme.html#topics) provide a high level overview of a specific concept or feature. These are **understanding-oriented**, and are perfect for discovering design patterns, features, and tools related to a given topic. * * * [**How-to**](readme.html#how-to) guides are **goal-oriented** recipes for accomplishing specific tasks. These are also good to browse to get an idea of how Ash works and what is possible with it. * * * [**Reference**](readme.html#reference) documentation is produced automatically from our source code. It comes in the form of module documentation and DSL documentation. This documentation is **information-oriented**. Use the sidebar and the search bar to find relevant reference information. ## [](readme.html#tutorials)Tutorials - [Get Started](get-started.html) * * * ## [](readme.html#topics)Topics ### [](readme.html#about-ash)About Ash - [What is Ash?](what-is-ash.html) - [Our Design Principles](design-principles.html) - [Contributing to Ash](contributing-to-ash.html) - [Alternatives](alternatives.html) ### [](readme.html#resources)Resources - [Domains](domains.html) - [Attributes](attributes.html) - [Relationships](relationships.html) - [Calculations](calculations.html) - [Aggregates](aggregates.html) - [Code Interfaces](code-interfaces.html) - [Identities](identities.html) - [Validations](validations.html) - [Changes](changes.html) - [Preparations](preparations.html) - [Embedded Resources](embedded-resources.html) - [Notifiers](notifiers.html) ### [](readme.html#actions)Actions - [Actions](actions.html) - [Read Actions](read-actions.html) - [Create Actions](create-actions.html) - [Update Actions](update-actions.html) - [Destroy Actions](destroy-actions.html) - [Generic Actions](generic-actions.html) - [Manual Actions](manual-actions.html) ### [](readme.html#security)Security - [Actors &amp; Authorization](actors-and-authorization.html) - [Sensitive Data](sensitive-data.html) - [Policies](policies.html) ### [](readme.html#development)Development - [Project Structure](project-structure.html) - [Generators](generators.html) - [Testing](testing.html) - [Development Utilities](development-utilities.html) - [Upgrading to 3.0](upgrading-to-3-0.html) - [Error Handling](error-handling.html) ### [](readme.html#advanced)Advanced - [Monitoring](monitoring.html) - [Multitenancy](multitenancy.html) - [Reactor](reactor.html) - [Timeouts](timeouts.html) - [Writing Extensions](writing-extensions.html) * * * ## [](readme.html#how-to)How-to - [Test Resources](test-resources.html) - [Authorize Access to Resources](authorize-access-to-resources.html) - [Encrypt Attributes](encrypt-attributes.html) - [Prevent Concurrent Writes](prevent-concurrent-writes.html) - [Wrap External APIs](wrap-external-apis.html) - [Define Polymorphic Relationships](polymorphic-relationships.html) * * * ## [](readme.html#reference)Reference - [Ash.Resource DSL](dsl-ash-resource.html) - [Ash.Domain DSL](dsl-ash-domain.html) - [Ash.Reactor DSL](dsl-ash-reactor.html) - [Ash.Notifier.PubSub DSL](dsl-ash-notifier-pubsub.html) - [Ash.Policy.Authorizer DSL](dsl-ash-policy-authorizer.html) - [Ash.DataLayer.Ets DSL](dsl-ash-datalayer-ets.html) - [Ash.DataLayer.Mnesia DSL](dsl-ash-datalayer-mnesia.html) - [Glossary](glossary.html) - [Expressions](expressions.html) - For other reference documentation, see the sidebar &amp; search bar ## [](readme.html#packages)Packages The Ash ecosystem consists of numerous packages, all of which have their own documentation. If you can't find something in this documentation, don't forget to search in any potentially relevant package. ### [](readme.html#data-layers)Data Layers - [AshPostgres](../ash_postgres.html) | PostgreSQL data layer - [AshSqlite](../ash_sqlite.html) | SQLite data layer - [AshCsv](../ash_csv.html) | CSV data layer - [AshCubdb](../ash_cubdb.html) | CubDB data layer ### [](readme.html#api-extensions)API Extensions - [AshJsonApi](../ash_json_api.html) | JSON:API builder - [AshGraphql](../ash_graphql.html) | GraphQL builder ### [](readme.html#web)Web - [AshPhoenix](../ash_phoenix.html) | Phoenix integrations - [AshAuthentication](../ash_authentication.html) | Authenticate users with password, OAuth, and more - [AshAuthenticationPhoenix](../ash_authentication_phoenix.html) | Integrations for AshAuthentication and Phoenix ### [](readme.html#finance)Finance - [AshMoney](../ash_money.html) | A money data type for Ash - [AshDoubleEntry](../ash_double_entry.html) | A double entry system backed by Ash Resources ### [](readme.html#resource-utilities)Resource Utilities - [AshOban](../ash_oban.html) | Background jobs and scheduled jobs for Ash, backed by Oban - [AshArchival](../ash_archival.html) | Archive resources instead of deleting them - [AshStateMachine](../ash_state_machine.html) | Create state machines for resources - [AshPaperTrail](../ash_paper_trail.html) | Keep a history of changes to resources - [AshCloak](../ash_cloak.html) | Encrypt attributes of a resource ### [](readme.html#admin-monitoring)Admin &amp; Monitoring - [AshAdmin](../ash_admin.html) | A push-button admin interface - [AshAppsignal](../ash_appsignal.html) | Monitor your Ash resources with AppSignal ### [](readme.html#testing)Testing - [Smokestack](../smokestack.html) | Declarative test factories for Ash resources ### [](readme.html#examples-external-resources)Examples &amp; External Resources - [Ash Real World](https://github.com/team-alembic/realworld) | Ash + Phoenix LiveView codebase containing real world examples (CRUD, auth, advanced patterns, etc) [← Previous Page API Reference](api-reference.html) [Next Page → Get Started](get-started.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/README.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Relationships [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/relationships.md#L1 "View Source") Relationships describe the connections between resources and are a core component of Ash. Defining relationships enables you to do things like - Loading related data - Filtering on related data - Managing related records through changes on a single resource - Authorizing based on the state of related data ## [](relationships.html#relationships-basics)Relationships Basics A relationship exists between a source resource and a destination resource. These are defined in the `relationships` block of the source resource. For example, if `MyApp.Tweet` is the source resource, and `MyApp.User` is the destination resource, we could define a relationship called `:owner` like this: ``` defmodule MyApp.Tweet do use Ash.Resource, data_layer: my_data_layer attributes do uuid_primary_key :id attribute :body, :string end relationships do belongs_to :owner, MyApp.User end end ``` ## [](relationships.html#managing-related-data)Managing related data See [Managing Relationships](relationships.html#managing-relationships) for more information. Your data layer may enforce foreign key constraints, see the following guides for more information: - [AshPostgres references](../ash_postgres/references.html) ## [](relationships.html#kinds-of-relationships)Kinds of relationships There are four kinds of relationships: - [`belongs_to`](relationships.html#belongs-to) - [`has_one`](relationships.html#has-one) - [`has_many`](relationships.html#has-many) - [`many_to_many`](relationships.html#many-to-many) Each of these relationships has a `source` resource and a `destination` resource with a corresponding attribute on the source resource (`source_attribute`), and destination resource (`destination_attribute`). Relationships will validate that their configured attributes exist at compile time. You don't need to have a corresponding "reverse" relationship for every relationship, i.e if you have a `MyApp.Tweet` resource with `belongs_to :user, MyApp.User` you aren't required to have a `has_many :tweets, MyApp.Tweet` on `MyApp.User`. All that is required is that the attributes used by the relationship exist. ### [](relationships.html#belongs-to)Belongs To ``` # on MyApp.Tweet belongs_to :owner, MyApp.User ``` A `belongs_to` relationship means that there is an attribute (`source_attribute`) on the source resource that uniquely identifies a record with a matching attribute (`destination_attribute`) in the destination. In the example above, the source attribute on `MyApp.Tweet` is `:owner_id` and the destination attribute on `MyApp.User` is `:id`. #### Attribute Defaults By default, the `source_attribute` is defined as `:<relationship_name>_id` of the type `:uuid` on the source resource and the `destination_attribute` is assumed to be `:id`. You can override the attribute names by specifying the `source_attribute` and `destination_attribute` options like so: ``` belongs_to :owner, MyApp.User do # defaults to :<relationship_name>_id (i.e. :owner_id) source_attribute :custom_attribute_name # defaults to :id destination_attribute :custom_attribute_name end ``` You can further customize the `source_attribute` using options such as: - `Ash.Resource.Dsl.relationships.belongs_to.define_attribute?` to define it yourself - `Ash.Resource.Dsl.relationships.belongs_to.attribute_type` to modify the default type - `Ash.Resource.Dsl.relationships.belongs_to.attribute_public?` to make the source attribute `public?: true` For example: ``` belongs_to :owner, MyApp.User do attribute_type :integer attribute_writable? false end ``` Or if you wanted to define the attribute yourself, ``` attributes do attribute :owner_foo, MyApp.CustomType end ... relationships do belongs_to :owner, MyApp.User do define_attribute? false source_attribute :owner_foo end end ``` #### Customizing default belongs\_to attribute type Destination attributes that are added by default are assumed to be `:uuid`. To change this, set the following configuration in `config.exs`: ``` config :ash, :default_belongs_to_type, :integer ``` See the docs for more: `Ash.Resource.Dsl.relationships.belongs_to` ### [](relationships.html#has-one)Has One ``` # on MyApp.User has_one :profile, MyApp.Profile ``` A `has_one` relationship means that there is a unique attribute (`destination_attribute`) on the destination resource that identifies a record with a matching unique attribute (`source_resource`) in the source. In the example above, the source attribute on `MyApp.User` is `:id` and the destination attribute on `MyApp.Profile` is `:user_id`. A `has_one` is similar to a `belongs_to` except the reference attribute is on the destination resource, instead of the source. #### Attribute Defaults By default, the `source_attribute` is assumed to be `:id`, and `destination_attribute` defaults to `<snake_cased_last_part_of_module_name>_id`. See the docs for more: `Ash.Resource.Dsl.relationships.has_one` ### [](relationships.html#has-many)Has Many ``` # on MyApp.User has_many :tweets, MyApp.Tweet ``` A `has_many` relationship means that there is a non-unique attribute (`destination_attribute`) on the destination resource that identifies a record with a matching attribute (`source_attribute`) in the source. In the example above, the source attribute on `MyApp.User` is `:id` and the destination attribute on `MyApp.Tweet` is `:user_id`. A `has_many` relationship is similar to a `has_one` because the reference attribute exists on the destination resource. The only difference between this and `has_one` is that the destination attribute is not unique, and therefore will produce a list of related items. In the example above, `:tweets` corresponds to a list of `MyApp.Tweet` records. #### Attribute Defaults By default, the `source_attribute` is assumed to be `:id`, and `destination_attribute` defaults to `<snake_cased_last_part_of_module_name>_id`. See the docs for more: `Ash.Resource.Dsl.relationships.has_many` ### [](relationships.html#many-to-many)Many To Many A `many_to_many` relationship can be used to relate many source resources to many destination resources. To achieve this, the `source_attribute` and `destination_attribute` are defined on a join resource. A `many_to_many` relationship can be thought of as a combination of a `has_many` relationship on the source/destination resources and a `belongs_to` relationship on the join resource. For example, consider two resources `MyApp.Tweet` and `MyApp.Hashtag` representing tweets and hashtags. We want to be able to associate a tweet with many hashtags, and a hashtag with many tweets. To do this, we could define the following `many_to_many` relationship: ``` # on MyApp.Tweet many_to_many :hashtags, MyApp.Hashtag do through MyApp.TweetHashtag source_attribute_on_join_resource :tweet_id destination_attribute_on_join_resource :hashtag_id end ``` The `through` option specifies the "join" resource that will be used to store the relationship. We need to define this resource as well: ``` defmodule MyApp.TweetHashtag do use Ash.Resource, data_layer: your_data_layer postgres do table "tweet_hashtags" repo MyApp.Repo end relationships do belongs_to :tweet, MyApp.Tweet, primary_key?: true, allow_nil?: false belongs_to :hashtag, MyApp.Hashtag, primary_key?: true, allow_nil?: false end actions do defaults [:read, :destroy, create: :*, update: :*] end end ``` It is convention to name this resource `<source_resource_name><destination_resource_name>` however this is not required. The attributes on the join resource must match the `source_attribute_on_join_resource` and `destination_attribute_on_join_resource` options on the `many_to_many` relationship. The relationships on the join resource are standard `belongs_to` relationships, and can be configured as such. In this case, we have specified that the `:tweet_id` and `:hashtag_id` attributes form the primary key for the join resource, and that they cannot be `nil`. Now that we have a resource with the proper attributes, Ash will use this automatically under the hood when performing relationship operations like filtering and loading. See the docs for more: `Ash.Resource.Dsl.relationships.many_to_many` ## [](relationships.html#loading-related-data)Loading related data There are two ways to load relationships: - in the query using [`Ash.Query.load/2`](Ash.Query.html#load/2) - directly on records using [`Ash.load/3`](Ash.html#load/3) ### [](relationships.html#on-records)On records Given a single record or a set of records, it is possible to load their relationships by calling the `load` function on the record's parent domain. For example: ``` # user = %User{...} Ash.load(user, :tweets) # users = [%User{...}, %User{...}, ....] Ash.load(users, :tweets) ``` This will fetch the tweets for each user, and set them in the corresponding `tweets` key. ``` %User{ ... tweets: [ %Tweet{...}, %Tweet{...}, ... ] } ``` See [`Ash.load/3`](Ash.html#load/3) for more information. ### [](relationships.html#in-the-query)In the query The following will return a list of users with their tweets loaded identically to the previous example: ``` User |> Ash.Query.load(:tweets) |> Ash.read() ``` At present, loading relationships in the query is fundamentally the same as loading on records. Eventually, data layers will be able to optimize these loads (potentially including them as joins in the main query). See [`Ash.Query.load/2`](Ash.Query.html#load/2) for more information. ### [](relationships.html#more-complex-data-loading)More complex data loading Multiple relationships can be loaded at once, i.e ``` Ash.load(users, [:tweets, :followers]) ``` Nested relationships can be loaded: ``` Ash.load(users, followers: [:tweets, :followers]) ``` The queries used for loading can be customized by providing a query as the value. ``` followers = Ash.Query.sort(User, follower_count: :asc) Ash.load(users, followers: followers) ``` Nested loads will be included in the parent load. ``` followers = User |> Ash.Query.sort(follower_count: :asc) |> Ash.Query.load(:followers) # Will load followers and followers of those followers Ash.load(users, followers: followers) ``` ## [](relationships.html#no_attributes-true)no\_attributes? true This is really useful when creating customized relationships that aren't joined with simple attribute matches. For example: ``` has_many :higher_priority_tickets, __MODULE__ do no_attributes? true # parent/1 in this case puts the expression on this current resource # so this is "tickets with priority higher than this ticket" filter expr(priority > parent(priority)) end ``` This can also be useful when combined with schema-based multitenancy. Specifically, if you have a tenant resource like `Organization`, you can use `no_attributes?` to do things like `has_many :employees, Employee, no_attributes?: true`, which lets you avoid having an unnecessary `organization_id` field on `Employee`. The same works in reverse: `has_one :organization, Organization, no_attributes?: true` allows relating the employee to their organization. You can also use `no_attributes? true` with attribute-based multitenancy in the same situation described above, to avoid an unnecessary second filter. If both resources have attribute multitenancy configured, they will already be filtered by `organization_id` by virtue of having set the tenant. ### [](relationships.html#caveats-for-using-no_attributes)Caveats for using `no_attributes?` 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. ## [](relationships.html#manual-relationships)Manual Relationships Manual relationships allow you to express complex or non-typical relationships between resources in a standard way. Individual data layers may interact with manual relationships in their own way, so see their corresponding guides. In general, you should try to use manual relationships sparingly, as you can do *a lot* with filters on relationships, and the `no_attributes?` flag. ### [](relationships.html#example)Example In our Helpdesk example, we'd like to have a way to find tickets In the `Representative` resource, define a `has_many` relationship as `manual` and point to the module where it will be implemented. ``` relationships do has_many :tickets_above_threshold, Helpdesk.Support.Ticket do manual Helpdesk.Support.Ticket.Relationships.TicketsAboveThreshold end end ``` Using Ash to get the destination records is ideal, so you can authorize access like normal but if you need to use a raw ecto query here, you can. As long as you return the right structure. The `TicketsAboveThreshold` module is implemented as follows. ``` defmodule Helpdesk.Support.Ticket.Relationships.TicketsAboveThreshold do use Ash.Resource.ManualRelationship require Ash.Query def load(records, _opts, %{query: query} = context) do # Use existing records to limit results rep_ids = Enum.map(records, & &1.id) {:ok, query |> Ash.Query.filter(representative_id in ^rep_ids) |> Ash.Query.filter(priority > representative.priority_threshold) |> Ash.read!(Ash.Context.to_opts(context)) # Return the items grouped by the primary key of the source, i.e representative.id => [...tickets above threshold] |> Enum.group_by(& &1.representative_id)} end end ``` ### [](relationships.html#reusing-the-query)Reusing the Query Since you likely want to support things like filtering your relationship when being loaded, you will want to make sure that you use the query being provided. However, depending on how you're loading the relationship, you may need to do things like fetch extra records. To do this, you might do things like ``` def load(records, _opts, %{query: query, ..}) do # unset some fields fetch_query = Ash.Query.unset(query, [:limit, :offset]) # or, to be more safe/explicit, you might make a new query, explicitly setting only a few fields fetch_query = query.resource |> Ash.Query.filter(^query.filter) |> Ash.Query.sort(query.sort) ... end ``` ### [](relationships.html#query-when-loading-with-strict-true)Query when loading with strict?: true When using `Ash.Query.load` or `Ash.load` with the `strict?: true` option, the query that is provided to the load callback might be configured with a select-statement that doesn't load the attributes you want to group matching results by. If your codebase utilizes the strict loading functionality, it is therefore recommended to use `Ash.Query.ensure_selected` on the query to ensure the required attributes are indeed fetched. ``` # Here only :id & :priority is set, which will then configure the relationship query to only # select those attributes {:ok, rep} = Ash.load(representative, [tickets_above_threshold: [:id, :priority]], strict?: true) defmodule Helpdesk.Support.Ticket.Relationships.TicketsAboveThreshold do use Ash.Resource.ManualRelationship require Ash.Query def load(records, _opts, %{query: query, actor: actor, authorize?: authorize?}) do rep_ids = Enum.map(records, & &1.id) {:ok, query # If this isn't added, representative_id would be set to %Ash.NotLoaded, causing the # Enum.group_by call below to fail mapping results to the correct records. |> Ash.Query.ensure_selected([:representative_id]) |> Ash.Query.filter(representative_id in ^rep_ids) |> Ash.Query.filter(priority > representative.priority_threshold) |> Helpdesk.Support.read!(actor: actor, authorize?: authorize?) |> Enum.group_by(& &1.representative_id)} end end ``` ### [](relationships.html#fetching-the-records-and-then-applying-a-query)Fetching the records and then applying a query Lets say the records come from some totally unrelated source, or you can't just modify the query to fetch the records you need. You can fetch the records you need and then apply the query to them in memory. ``` def load(records, _opts, %{query: query, ..}) do # fetch the data from the other source, which is capable of sorting data = get_other_data(data, query.sort) query # unset the sort since we already applied that |> Ash.Query.unset([:sort]) # apply the query in memory (filtering, distinct, limit, offset) |> Ash.Query.apply_to(data) end ``` ## [](relationships.html#managing-relationships)Managing Relationships In Ash, managing related data is done via [`Ash.Changeset.manage_relationship/4`](Ash.Changeset.html#manage_relationship/4). There are various ways to leverage the functionality expressed there. If you are working with changesets directly, you can call that function. However, if you want that logic to be portable (e.g available in `ash_graphql` mutations and `ash_json_api` actions), then you want to use the following `argument` + `change` pattern: ``` actions do update :update do argument :add_comment, :map do allow_nil? false end argument :tags, {:array, :uuid} do allow_nil? false end # First argument is the name of the action argument to use # Second argument is the relationship to be managed # Third argument is options. For more, see `Ash.Changeset.manage_relationship/4`. This accepts the same options. change manage_relationship(:add_comment, :comments, type: :create) # Second argument can be omitted, as the argument name is the same as the relationship change manage_relationship(:tags, type: :append_and_remove) end end ``` With this, those arguments can be used in action input: ``` post |> Ash.Changeset.for_update(:update, %{tags: [tag1.id, tag2.id], add_comment: %{text: "comment text"}}) |> Ash.update!() ``` ### [](relationships.html#argument-types)Argument Types Notice how we provided a map as input to `add_comment`, and a list of UUIDs as an input to `manage_relationship`. When providing maps or lists of maps, you are generally just providing input that will eventually be passed into actions on the destination resource. However, you can also provide individual values or lists of values. By default, we assume that value maps to the primary key of the destination resource, but you can use the `value_is_key` option to modify that behavior. For example, if you wanted adding a comment to take a list of strings, you could say: ``` argument :add_comment, :string ... change manage_relationship(:add_comment, :comments, type: :create, value_is_key: :text) ``` And then you could use it like so: ``` post |> Ash.Changeset.for_update(:update, %{tags: [tag1.id, tag2.id], add_comment: "comment text"}) |> Ash.update!() ``` ### [](relationships.html#derived-behavior)Derived behavior Determining what will happen when managing related data can be complicated, as the nature of the problem itself is quite complicated. In some simple cases, like `type: :create`, there may be only one action that will be called. But in order to support all of the various ways that related resources may need to be managed, Ash provides a rich set of options to determine what happens with the provided input. Tools like `AshPhoenix.Form` can look at your arguments that have a corresponding `manage_relationship` change, and derive the structure of those nested forms. Tools like `AshGraphql` can derive complex input objects to allow manipulating those relationships over a graphql Api. This all works because the options are, ultimately, quite explicit. It can be determined exactly what actions might be called, and therefore what input could be needed. To see all of the options available, see [`Ash.Changeset.manage_relationship/4`](Ash.Changeset.html#manage_relationship/4) [← Previous Page Attributes](attributes.html) [Next Page → Calculations](calculations.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/relationships.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Sensitive Data [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/security/sensitive-data.md#L1 "View Source") ## [](sensitive-data.html#public-private-attributes)Public &amp; Private Attributes By default, attributes, calculations, aggregates and relationships are *private* (they are marked `public?: false`). If you are working with Ash in code, reading a resource, for example using [`Ash.read/2`](Ash.html#read/2), the public/private status of an attribute is not relevant. However, when working with api extensions like `AshGraphql` and `AshJsonApi`, they will only include public fields in their interfaces. This helps avoid accidentally exposing data over "public" interfaces. ## [](sensitive-data.html#public-private-arguments)Public &amp; Private Arguments Public/private arguments work the same way as public/private fields, except that they default to `public?: true`. This is because arguments to an action being used in a public interface would naturally be expected to be `public`. If an argument is marked as `public?: false`, it can only be set with [`Ash.Query.set_argument/3`](Ash.Query.html#set_argument/3) or [`Ash.Changeset.set_argument/3`](Ash.Changeset.html#set_argument/3) ## [](sensitive-data.html#sensitive-attributes)Sensitive Attributes Using `sensitive? true` will cause an attribute, calculation or argument to show as `"** Redacted **"` when inspecting records. In filter statements, any value used in the same expression as a sensitive field will also be redacted. For example, you might see: `email == "** Redacted **"` in a filter statement if `email` is marked as sensitive. ### [](sensitive-data.html#show-sensitive-attributes)Show Sensitive Attributes **IMPORTANT WARNING:** The following configuration should only ever be used in development mode! To display sensitive attributes in their original form during development, use the following config. ``` config :ash, show_sensitive?: true ``` ## [](sensitive-data.html#field-policies)Field Policies Field policies are a way to control the visibility of individual fields (except for relationships) as a part of authorization flow, for those using [`Ash.Policy.Authorizer`](Ash.Policy.Authorizer.html). If a field is not visible, it will be populated with `%Ash.ForbiddenField{}`, or will be not shown (or may show an error) in public interfaces. See the [Policies guide](policies.html#field-policies) for more. [← Previous Page Actors &amp; Authorization](actors-and-authorization.html) [Next Page → Policies](policies.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/security/sensitive-data.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Testing [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/development/testing.md#L1 "View Source") Take a look at [the how-to guide](test-resources.html) for a practical look at writing tests The configuration you likely want to add to your `config/test.exs` is: ``` # config/test.exs config :ash, :disable_async?, true config :ash, :missed_notifications, :ignore ``` Each option is explained in more detail below. ## [](testing.html#async-tests)Async tests The first thing you will likely want to do, especially if you are using `AshPostgres`, is to add the following config to your `config/test.exs`. ``` # config/test.exs config :ash, :disable_async?, true ``` This ensures that Ash does not spawn tasks when executing your requests, which is necessary for doing transactional tests with `AshPostgres`. ## [](testing.html#missed-notifications)Missed notifications If you are using Ecto's transactional features to ensure that your tests all run in a transaction, Ash will detect that it had notifications to send (if you have any notifiers set up) but couldn't because it was still in a transaction. The default behavior when notifications are missed is to warn. However, this can get pretty noisy in tests. So we suggest adding the following config to your `config/test.exs`. ``` # config/test.exs config :ash, :missed_notifications, :ignore ``` [← Previous Page Error Handling](error-handling.html) [Next Page → Development Utilities](development-utilities.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/development/testing.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Test Resources [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/how-to/test-resources.livemd#L1 "View Source") [![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](test-resources.html) ``` Mix.install([{:ash, "~> 3.0"}, {:simple_sat, "~> 0.1"}], consolidate_protocols: false ) Logger.configure(level: :warning) ExUnit.start() ``` ## [](test-resources.html#introduction)Introduction We recommend testing your resources *thoroughly*. Often, folks think that testing an [`Ash.Resource`](Ash.Resource.html) is "testing the framework", and in some very simple cases this may be true, like a simple create that just accepts a few attributes. However, testing has two primary roles: 1. Confirming our understanding of the way that our application behaves *now* 2. Ensuring that our application does not change in unintended ways *later* To this end, we highly recommend writing tests even for your simple actions. A single test that confirms that, with simple inputs, the action returns what you expect, can be very powerful. Additionally, Ash offers unique ways of testing individual components of our resources, similar to a unit test. While you don't necessarily need to follow all steps below, we show the various ways you may want to go about testing your resources. ## [](test-resources.html#testing-resources)Testing Resources - Add tests for action inputs using property testing - Add tests for calling action invocation using property testing - Add explicit tests for action inputs/invocation. - Add tests for our calculations - Test policies "in isolation" using `Ash.can?` (or `Domain.can_*`, provided by code interfaces) ## [](test-resources.html#examples)Examples ``` defmodule User do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets actions do defaults [:read, create: [:admin?]] end attributes do uuid_primary_key :id attribute :admin?, :boolean do allow_nil? false default false end end end defmodule Tweet do use Ash.Resource, domain: Domain, data_layer: Ash.DataLayer.Ets, authorizers: [Ash.Policy.Authorizer] attributes do uuid_primary_key :id attribute :text, :string do allow_nil? false constraints max_length: 144 public? true end attribute :hidden?, :boolean do allow_nil? false default false public? true end end calculations do calculate :tweet_length, :integer, expr(string_length(text)) end relationships do belongs_to :user, User, allow_nil?: false end actions do defaults [:read, update: [:text]] create :create do primary? true accept [:text] change relate_actor(:user) end end policies do policy action_type(:read) do description "If a tweet is hidden, only the author can read it. Otherwise, anyone can." authorize_if relates_to_actor_via(:user) forbid_if expr(hidden? == true) authorize_if always() end policy action_type(:create) do description "Anyone can create a tweet" authorize_if always() end policy action_type(:update) do description "Only an admin or the user who tweeted can edit their tweet" authorize_if actor_attribute_equals(:admin?, true) authorize_if relates_to_actor_via(:user) end end end defmodule Domain do use Ash.Domain, validate_config_inclusion?: false resources do resource Tweet do define :create_tweet, action: :create, args: [:text] define :update_tweet, action: :update, args: [:text] define :list_tweets, action: :read end resource User do define :create_user, action: :create end end end ``` ``` {:module, Domain, <<70, 79, 82, 49, 0, 2, 46, ...>>, [ Ash.Domain.Dsl.Resources.Resource, Ash.Domain.Dsl.Resources.Options, Ash.Domain.Dsl, %{opts: [], entities: [...]}, Ash.Domain.Dsl, Ash.Domain.Dsl.Resources.Options, ... ]} ``` ## [](test-resources.html#write-some-tests)Write some tests ``` defmodule ActionInvocationTest do use ExUnit.Case import ExUnitProperties describe "valid inputs" do # now if our action inputs are invalid when we think they should be valid, we will find out here property "accepts all valid input" do user = Domain.create_user!() check all(input <- Ash.Generator.action_input(Tweet, :create)) do {text, other_inputs} = Map.pop!(input, :text) assert Domain.changeset_to_create_tweet( text, other_inputs, authorize?: false, actor: user ).valid? end end # same as the above, but actually call the action. This tests the underlying action implementation # not just initial validation property "succeeds on all valid input" do user = Domain.create_user!() check all(input <- Ash.Generator.action_input(Tweet, :create)) do {text, other_inputs} = Map.pop!(input, :text) Domain.create_tweet!(text, other_inputs, authorize?: false, actor: user) end end test "can tweet some specific text, in addition to any other valid inputs" do user = Domain.create_user!() check all( input <- Ash.Generator.action_input(Tweet, :create, %{text: "some specific text"}) ) do {text, other_inputs} = Map.pop!(input, :text) Domain.create_tweet!(text, other_inputs, actor: user) end end end describe "authorization" do test "allows a user to update their own tweet" do user = Domain.create_user!() tweet = Domain.create_tweet!("Hello world!", actor: user) assert Domain.can_update_tweet?(user, tweet, "Goodbye world!") end test "does not allow a user to update someone elses tweet" do user = Domain.create_user!() user2 = Domain.create_user!() tweet = Domain.create_tweet!("Hello world!", actor: user) refute Domain.can_update_tweet?(user2, tweet, "Goodbye world!") end test "allows an admin user to update someone elses tweet" do user = Domain.create_user!() user2 = Domain.create_user!(%{admin?: true}) tweet = Domain.create_tweet!("Hello world!", actor: user) assert Domain.can_update_tweet?(user2, tweet, "Goodbye world!") end end describe "calculations" do test "text length calculation computes the length of the text" do user = Domain.create_user!() tweet = Domain.create_tweet!("Hello world!", actor: user) assert Ash.calculate!(tweet, :tweet_length) == 12 end end end ExUnit.run() ``` ``` ....... Finished in 0.07 seconds (0.00s async, 0.07s sync) 2 properties, 5 tests, 0 failures Randomized with seed 42546 ``` ``` %{total: 7, failures: 0, skipped: 0, excluded: 0} ``` [← Previous Page Define Polymorphic Relationships](polymorphic-relationships.html) [Next Page → Authorize Access to Resources](authorize-access-to-resources.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/how-to/test-resources.livemd)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Timeouts [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/advanced/timeouts.md#L1 "View Source") ## [](timeouts.html#ways-to-specify-timeouts)Ways to Specify Timeouts You have a few options. You can specify a timeout when you call an action. This takes the highest precedence. ``` Ash.read!(query, timeout: :timer.seconds(30)) ``` You can specify one using [`Ash.Changeset.timeout/2`](Ash.Changeset.html#timeout/2) or [`Ash.Query.timeout/2`](Ash.Query.html#timeout/2). This can be useful if you want to conditionally set a timeout based on the details of the request. For example, you might do something like this: ``` # in your resource defmodule MyApp.SetReportTimeout do use Ash.Resource.Preparation def prepare(query, _, _) do if Ash.Query.get_argument(query, :full_report) do Ash.Query.timeout(query, :timer.minutes(3)) else Ash.Query.timeout(query, :timer.minutes(1)) end end end actions do read :report_items do argument :full_report, :boolean, default: false prepare MyApp.SetReportTimeout end end ``` You can also specify a default timeout on your domain modules. ``` execution do timeout :timer.seconds(30) # the default is `:infinity` end ``` Keep in mind, you can't specify timeouts in a before\_action or after\_action hook, because at that point you are already "within" the code that should have a timeout applied. ### [](timeouts.html#timeouts-use-processes)timeouts use processes Timeouts are implemented using processes. This means that potentially large query results will be copied across processes. Because of this, specifying timeouts globally or for things that you don't suspect would ever exceed that timeout is not recommended. ## [](timeouts.html#how-are-timeouts-handled)How are timeouts handled? Timeouts in Ash work a bit differently than other tools. The following considerations must be taken into account: 1. If you run a resource action in a transaction, then the timeout applies to the entire transaction. 2. If the resource action you are running, and any of its `touches_resources` is *already in a transaction* then the timeout is ignored, as the outer transaction is handling the timeout. 3. If the resource is not in a transaction, and supports async execution (ash\_postgres does), then everything is run in a task and awaited with the provided timeout. 4. If the data layer of the resource does not support timeouts, or async execution then timeouts are **ignored**. [← Previous Page Pagination](pagination.html) [Next Page → Multitenancy](multitenancy.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/advanced/timeouts.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Update Actions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/actions/update-actions.md#L1 "View Source") Update actions are used to update records in the data layer. For example: ``` # on a ticket resource update :close do accept [:close_reason] change set_attribute(:status, :closed) end ``` Here we have an update action called `:close` that allows setting the `close_reason`, and sets the `status` to `:closed`. It could be called like so: ``` ticket # providing an initial ticket to close |> Ash.Changeset.for_update(:close, %{close_reason: "I figured it out."}) |> Ash.update!() ``` For a full list of all of the available options for configuring update actions, see [the Ash.Resource.Dsl documentation](dsl-ash-resource.html#actions-update). See the [Code Interface guide](code-interfaces.html) for creating an interface to call the action more elegantly, like so: ``` Support.close_ticket!(ticket, "I figured it out.") # You can also provide an id Support.close_ticket!(ticket.id, "I figured it out.") ``` ## [](update-actions.html#atomics)Atomics Atomic updates can be added to a changeset, which will update the value of an attribute given by an expression. Atomics can be a very powerful way to model updating data in a simple way. An action does not have to be [fully atomic](update-actions.html#fully-atomic-updates) in order to leverage atomic updates. For example: ``` update :add_to_name do argument :to_add, :string, allow_nil? false change atomic_update(:name, expr("#{name}_#{to_add}")) end ``` Changing attributes in this way makes them safer to use in concurrent environments, and is typically more performant than doing it manually in memory. ### [](update-actions.html#atomics-are-not-stored-with-other-changes)Atomics are not stored with other changes While we recommend using atomics wherever possible, it is important to note that they are stored in their own map in the changeset, i.e `changeset.atomics`, meaning if you need to do something later in the action with the new value for an attribute, you won't be able to access the new value. This is because atomics are evaluated in the data layer. You can, however, access "the old or new value" in a similar way to `Ash.Changeset.get_attribute`, using the template expression, `atomic_ref(:name)`. See the section below for more. ### [](update-actions.html#atomic_ref-1)`atomic_ref/1` Lets say that you have an action that may perform multiple atomic update on a single column, or for some other reason needs to refer to the new value. The only way to access that new value is *also* in an atomic update, change, or validation, using `atomic_ref/1`. There is no way to access the new value prior to the action being run with something like [`Ash.Changeset.get_attribute/2`](Ash.Changeset.html#get_attribute/2). For example, lets say you have a postgres function that will slugify a string, and you want to make sure to always set it to the slugified version of `name`, whenever `name` is changing. ``` changes do change atomic_update(:slug, expr(fragment("slugify(?)", ^atomic_ref(:name)))), where: changing(:name), on: [:update] end ``` By using `atomic_ref/1` here, you are always referring to the new value of `name`, even if another atomic update has been made that modifies `name`. Because the validation `changing/1` can be done atomically, and the change `atomic_update/2` (naturally) can be done atomically, this is a fully atomic update. Lets say that you paired this with an action like this: ``` update :add_to_name do argument :to_add, :string, allow_nil? false change atomic_update(:name, expr("#{name}_#{to_add}")) end ``` and would produce a SQL update along the lines of: ``` UPDATE table SET name = name || $1, slug = CASE WHEN name = name || $1 THEN slug ELSE slugify(name || $1) END WHERE id = $2 ``` This is a *fully atomic update*, because all changes are done atomically in the data layer. We now have the benefits of composable building blocks *and* atomic updates. ## [](update-actions.html#fully-atomic-updates)Fully Atomic updates Atomic updates are a special case of update actions that can be done completely atomically. If your update action can't be done atomically, you will get an error unless you have set `require_atomic? false`. This is to encourage you to opt for atomic updates whereever reasonable. Not all actions can reasonably be made atomic, and not all non-atomic actions are problematic for concurrency. The goal is only to make sure that you are aware and have considered the implications. ### [](update-actions.html#what-does-atomic-mean)What does atomic mean? An atomic update is one that can be done in a single operation in the data layer. This ensures that there are no issues with concurrent access to the record being updated, and that it is as performant as possible. For example, the following action cannot be done atomically, because it has an anonymous function change on it. ``` update :increment_score do change fn changeset, _ -> Ash.Changeset.change_attribute(changeset, :score, changeset.data.score + 1) end end ``` The action shown above is not safe to run concurrently. If two separate processes fetch the record with score `1`, and then call `increment_score`, they will both set the score to `2`, when what you almost certainly intended to do was end up with a score of `3` By contrast, the following action *can* be done atomically ``` update :increment_score do change atomic_update(:score, expr(score + 1)) end ``` In a SQL data layer, this would produce SQL along the lines of ``` "UPDATE table SET score = score + 1 WHERE id = post_id" ``` ## [](update-actions.html#what-makes-an-action-not-atomic)What makes an action not atomic? ### [](update-actions.html#types-that-can-t-be-atomically-casted)Types that can't be atomically casted Not all types support being casted atomically. For instance, `:union` types, and embedded resources that have primary keys(and therefore may need to use an update action) cannot currently be casted atomically. ### [](update-actions.html#changes-without-an-atomic-callback)Changes without an `atomic` callback Changes can be enhanced to support atomics by defining [`Ash.Resource.Change.atomic/3`](Ash.Resource.Change.html#c:atomic/3). This callback can return a map of atomic updates to be made to attributes. Here is a simplified example from the built in [`Ash.Resource.Change.Builtins.increment/2`](Ash.Resource.Change.Builtins.html#increment/2) change: ``` @impl true def atomic(_changeset, opts, _context) do # Set the requested attribute to its current value (atomic_ref) + the amount {:atomic, %{opts[:attribute] => expr(^atomic_ref(opts[:attribute]) + ^opts[:amount])}} end ``` ### [](update-actions.html#validations-without-an-atomic-callback)Validations without an `atomic` callback Validations can be enhanced to support atomics by defining [`Ash.Resource.Validation.atomic/3`](Ash.Resource.Validation.html#c:atomic/3). This callback can return an atomic validation (or a list of atomic validations), which is represented by a list of affected attributes (not currently used), an expression that should trigger an error, and the expression producing the error. Here is an example from the built in `Ash.Resource.Validations.Builtins.attribute_equals/2` validation: ``` @impl true def atomic(_changeset, opts, context) do {:atomic, [opts[:attribute]], expr(^atomic_ref(opts[:attribute]) != ^opts[:value]), expr( error(^InvalidAttribute, %{ field: ^opts[:attribute], value: ^atomic_ref(opts[:attribute]), message: ^(context.message || "must equal %{value}"), vars: %{field: ^opts[:attribute], value: ^opts[:value]} }) )} end ``` ## [](update-actions.html#bulk-updates)Bulk updates There are three strategies for bulk updating data. They are, in order of preference: `:atomic`, `:atomic_batches`, and `:stream`. When calling [`Ash.bulk_update/4`](Ash.html#bulk_update/4), you can provide a strategy or strategies that can be used, and Ash will choose the best one available. The implementation of the update action and the capabilities of the data layer determine what strategies can be used. ## [](update-actions.html#atomic)Atomic Atomic bulk updates are used when the subject of the bulk update is a query, and the update action [can be done atomically](update-actions.html#fully-atomic-updates) and the data layer supports updating a query. They map to a single statement to the data layer to update all matching records. The data layer must support updating a query. ### [](update-actions.html#example)Example ``` Ticket |> Ash.Query.filter(status == :open) |> Ash.bulk_update!(:close, %{reason: "Closing all open tickets."}) ``` If using a SQL data layer, this would produce a query along the lines of ``` UPDATE tickets SET status = 'closed', reason = 'Closing all open tickets.' WHERE status = 'open'; ``` ## [](update-actions.html#atomic-batches)Atomic Batches Atomic batches is used when the subject of the bulk update is an enumerable (i.e list or stream) of records and the update action [can be done atomically](update-actions.html#fully-atomic-updates) and the data layer supports updating a query. The records are pulled out in batches, and then each batch follows the logic described [above](update-actions.html#atomic). The batch size is controllable by the `batch_size` option. ### [](update-actions.html#example-1)Example ``` Ash.bulk_update!(one_hundred_tickets, :close, %{reason: "Closing all open tickets."}, batch_size: 10) ``` If using a SQL data layer, this would produce ten queries along the lines of ``` UPDATE tickets SET status = 'closed', reason = 'Closing all open tickets.' WHERE id IN (...ids) ``` ## [](update-actions.html#stream)Stream Stream is used when the update action [cannot be done atomically](update-actions.html#fully-atomic-updates) or if the data layer does not support updating a query. If a query is given, it is run and the records are used as an enumerable of inputs. If an enumerable of inputs is given, each one is updated individually. There is nothing inherently wrong with doing this kind of update, but it will naturally be slower than the other two strategies. The benefit of having a single interface ([`Ash.bulk_update/4`](Ash.html#bulk_update/4)) is that the caller doesn't need to change based on the performance implications of the action. ## [](update-actions.html#running-a-standard-update-action)Running a standard update action All actions are run in a transaction if the data layer supports it. You can opt out of this behavior by supplying `transaction?: false` when creating the action. When an action is being run in a transaction, all steps inside of it are serialized because transactions cannot be split across processes. - Authorization is performed on the changes - A before action hook is added to set up belongs\_to relationships that are managed. This means potentially creating/modifying the destination of the relationship, and then changing the `destination_attribute` of the relationship. - `before_transaction` and `around_transaction` hooks are called ([`Ash.Changeset.before_transaction/2`](Ash.Changeset.html#before_transaction/2)). Keep in mind, any validations that are marked as `before_action? true` (or all global validations if your action has `delay_global_validations? true`) will not have happened at this point. - A transaction is opened if the action is configured for it (by default they are) and the data layer supports transactions - `before_action` hooks are performed in order - The main action is sent to the data layer - `after_action` hooks are performed in order - Non-belongs-to relationships are managed, creating/updating/destroying related records. - The transaction is closed, if one was opened - `after_transaction` hooks are invoked with the result of the transaction (even if it was an error) ## [](update-actions.html#atomic-upgrade)Atomic Upgrade Update actions that are run as "normal" update actions will, at the time of execution, be "upgraded" to an atomic action if possible. This means taking the original inputs and building a corresponding atomic action. This behavior is primarily useful for using things like `AshPhoenix.Form`, where you want to validate and see the effects of an action before running it, but want the ultimate invocation to be atomic (i.e concurrency safe). You can disable this by adding `atomic_upgrade? false` to the action configuration. Additionally, you may want to configure the read action used for atomic upgrades (defaults to the primary read), with `atomic_upgrade_with` option, i.e `atomic_upgrade_with :list_all` [← Previous Page Create Actions](create-actions.html) [Next Page → Destroy Actions](destroy-actions.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/actions/update-actions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Validations [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/resources/validations.md#L1 "View Source") Validations are similar to [changes](changes.html), except they cannot modify the changeset. They can only continue, or add an error. ## [](validations.html#builtin-validations)Builtin Validations There are a number of builtin validations that can be used, and are automatically imported into your resources. See [`Ash.Resource.Validation.Builtins`](Ash.Resource.Validation.Builtins.html) for more. Some examples of usage of builtin validations ``` validate match(:email, ~r/@/) validate compare(:age, greater_than_or_equal_to: 18) do message "must be over 18 to sign up" end validate present(:last_name) do where [present(:first_name), present(:middle_name)] message "must also be supplied if setting first name and middle_name" end ``` ## [](validations.html#custom-validations)Custom Validations ``` defmodule MyApp.Validations.IsPrime do # transform and validate opts use Ash.Resource.Validation @impl true def init(opts) do if is_atom(opts[:attribute]) do {:ok, opts} else {:error, "attribute must be an atom!"} end end @impl true def validate(changeset, opts, _context) do value = Ash.Changeset.get_attribute(changeset, opts[:attribute]) # this is a function I made up for example if is_nil(value) || Math.is_prime?(value) do :ok else # The returned error will be passed into `Ash.Error.to_ash_error/3` {:error, field: opts[:attribute], message: "must be prime"} end end end ``` This could then be used in a resource via: ``` validate {MyApp.Validations.IsPrime, attribute: :foo} ``` ## [](validations.html#anonymous-function-validations)Anonymous Function Validations You can also use anonymous functions for validations. Keep in mind, these cannot be made atomic. This is great for prototyping, but we generally recommend using a module, both for organizational purposes, and to allow adding atomic behavior. ``` validate fn changeset, _context -> # put your code here end ``` ## [](validations.html#where)Where The `where` can be used to perform validations conditionally. The value of the `where` option can either be a validation or a list of validations. All of the `where`-validations must first pass for the main validation to be applied. For expressing complex conditionals, passing a list of built-in validations to `where` can serve as an alternative to writing a custom validation module. ### [](validations.html#examples)Examples ``` validate present(:other_number), where: absent(:that_number) ``` ``` validate present(:other_number) do where {MyApp.Validations.IsPrime, attribute: :foo} end ``` ``` validate present(:other_number), where: [ numericality(:large_number, greater_than: 100), one_of(:magic_number, [7, 13, 123]) ] ``` ## [](validations.html#action-vs-global-validations)Action vs Global Validations You can place a validation in any create, update, or destroy action. For example: ``` actions do create :create do validate compare(:age, greater_than_or_equal_to: 18) end end ``` Or you can use the global validations block to validate on all actions of a given type. Where statements can be used in either. Note the warning about running on destroy actions below. ``` validations do validate present([:foo, :bar], at_least: 1) do on [:create, :update] where present(:baz) end end ``` The validations section allows you to add validations across multiple actions of a changeset ### [](validations.html#running-on-destroy-actions)Running on destroy actions By default, validations in the global `validations` block will run on create and update only. Many validations don't make sense in the context of destroys. To make them run on destroy, use `on: [:create, :update, :destroy]` ### [](validations.html#examples-1)Examples ``` validations do validate present([:foo, :bar]), on: :update validate present([:foo, :bar, :baz], at_least: 2), on: :create validate present([:foo, :bar, :baz], at_least: 2), where: [action_is(:action1, :action2)] validate absent([:foo, :bar, :baz], exactly: 1), on: [:update, :destroy] validate {MyCustomValidation, [foo: :bar]}, on: :create end ``` ## [](validations.html#atomic-validations)Atomic Validations To make a validation atomic, you have to implement the [`Ash.Resource.Validation.atomic/3`](Ash.Resource.Validation.html#c:atomic/3) callback. This callback returns an atomic instruction, or a list of atomic instructions, or an error/indication that the validation cannot be done atomically. For our `IsPrime` example above, this would look something like: ``` defmodule MyApp.Validations.IsPrime do # transform and validate opts use Ash.Resource.Validation ... def atomic(changeset, opts, context) do # lets ignore that there is no easy/built-in way to check prime numbers in postgres {:atomic, # the list of attributes that are involved in the validation [opts[:attribute]], # the condition that should cause the error # here we refer to the new value or the current value expr(not(fragment("is_prime(?)", ^atomic_ref(opts[:attribute])))), # the error expression expr( error(^InvalidAttribute, %{ field: ^opts[:attribute], # the value that caused the error value: ^atomic_ref(opts[:attribute]), # the message to display message: ^(context.message || "%{field} must be prime"), vars: %{field: ^opts[:attribute]} }) ) } end end ``` In some cases, validations operate on arguments only and therefore have no need of atomic behavior. for this, you can call `validate/3` directly from `atomic/3`. The builtin [`Ash.Resource.Validation.Builtins.argument_equals/2`](Ash.Resource.Validation.Builtins.html#argument_equals/2) validation does this, for example. ``` @impl true def atomic(changeset, opts, context) do validate(changeset, opts, context) end ``` [← Previous Page Aggregates](aggregates.html) [Next Page → Changes](changes.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/resources/validations.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # What is Ash? [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/about_ash/what-is-ash.md#L1 "View Source") Ash is an opinionated, composable set of application building blocks designed for extensibility. It shines when building web apps, APIs and services (though it can be used for any kind of Elixir application). It has integrations for Phoenix, LiveView, Postgres, GraphQL, Oban, and many more. To achieve this Ash provides a "Resource" abstraction you use to model the heart of your application. These resources then determine the database schema, API endpoints, state machines, background jobs, and more. Resources are the source of truth for your entire application, and everything stems from them. Ash is a declarative framework with deep extensibility. We provide a suite of extensions informed from building production apps, as well as a toolkit so you can build your own. We provide escape hatches ranging from the simple and small to the ability to override large pieces of behavior. Your Ash application is just an Elixir application, so if you want to do something completely custom then Ash won’t get in your way. It is not a web framework, like Phoenix or Rails. It is a framework for building your application layer, independent of how it is exposed or consumed. It is not an **alternative** to frameworks like Phoenix, rather a **complement** to them. #### Model your domain, derive the rest Ash derives significant portions of your application directly from your resources, with little to no effort required. This allows you to focus on what matters most: your business logic. We leverage the best of the Elixir ecosystem under the hood, providing a single unified tool-chain for our users. * * * A good analogy is design systems in the world of web development. When you use a design system, you get a set of components that are designed to work together, and you can build your application by combining these components in different ways. Ash is like a design system for your application's domain model. Or, for a less technical analogy, Ash is like a fully stocked workshop. When you arrive at the workshop, you may need to learn where everything is, but once you do, you have everything you need to build anything you can dream up. ## [](what-is-ash.html#why-should-i-use-it)Why should I use it? The fundamental idea behind Ash is that when the various components of your system can have consistent expectations of how the other components around them work, you can ultimately do a significant amount more, with less. For example, once you've defined your resources, it takes only a few additional lines of code to have your database structure generated, and a full featured API built around it. Ash has many use cases, with varying degrees of complexity. Ash helps you on day 1 of your project, removing boiler plate and allowing you to focus on the essential complexity of your application. It also helps you on year 5, lending consistency, code reuse, and maintainability. #### Ash is a force multiplier Things that once took days or weeks can be done in hours, and to a degree of quality that would have been unreasonable before. Entire classes of bugs are eliminated. And the best part is, you can do all of this without sacrificing the flexibility, robustness and ecosystem that Elixir is known for. ## [](what-is-ash.html#watch-the-elixirconf-2023-talk)Watch the ElixirConf 2023 Talk [← Previous Page Get Started](get-started.html) [Next Page → Design Principles](design-principles.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/about_ash/what-is-ash.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Wrap External APIs [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/how-to/wrap-external-apis.livemd#L1 "View Source") [![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](wrap-external-apis.html) ``` Mix.install( [ {:ash, "~> 3.0"}, {:req, "~> 0.4.0"} ], consolidate_protocols: false ) ``` ## [](wrap-external-apis.html#introduction)Introduction Wrapping external APIs in Ash resources can allow you to leverage the rich and consistent interface provided by [`Ash.Resource`](Ash.Resource.html) for interactions with external services. There are a few approaches to how you might do this, including the still in progress [AshJsonApiWrapper](https://github.com/ash-project/ash_json_api_wrapper). Here we will leverage "manual actions" as this is fully supported by Ash, and is the commonly used approach. This approach is most appropriate when you are working with an API that exposes some data, like entities, list of entities, etc. For this example, we will be interacting with [https://openlibrary.org](https://openlibrary.org), which allows for us to search and list books. This guide covers reading data from the external API, not creating/updating it. This can be implemented using manual actions of a different type, or generic actions. ## [](wrap-external-apis.html#wrapping-external-apis)Wrapping External APIs 1. Create a resource for interacting with the given API 2. Create a manual read action 3. In this manual action, we will: 1. call the target API 2. transform the results 3. apply query operations to simulate capabilities provided by Ash In the example below, we are calling to a *paginated* API, and we want to continue fetching results until we have reached the amount of results requested by the [`Ash.Query`](Ash.Query.html). We show this to illustrate that you can do all kinds of creative things when working with external APIs in manual actions. ## [](wrap-external-apis.html#example)Example ``` defmodule Doc do use Ash.Resource, domain: Domain attributes do uuid_primary_key :id attribute :author_name, :string attribute :title, :string attribute :type, :string end actions do read :search do primary? true argument :query, :string, allow_nil?: false prepare fn query, _ -> # We require that they limit the results to some reasonable set # (because this API is huge) cond do query.limit && query.limit > 250 -> Ash.Query.add_error(query, "must supply a limit that is less than or equal to 250") query.limit -> query true -> # limit 5 by default Ash.Query.limit(query, 5) end end manual Doc.Actions.Read end end end defmodule Domain do use Ash.Domain, validate_config_inclusion?: false resources do resource Doc do define :search, args: [:query] end end end ``` ``` {:module, Domain, <<70, 79, 82, 49, 0, 0, 250, ...>>, [ Ash.Domain.Dsl.Resources.Resource, Ash.Domain.Dsl.Resources.Options, Ash.Domain.Dsl, %{opts: [], entities: [...]}, Ash.Domain.Dsl, Ash.Domain.Dsl.Resources.Options, ... ]} ``` ``` defmodule Doc.Actions.Read do use Ash.Resource.ManualRead def read(query, _, _opts, _context) do # we aren't handling these query options to keep the example simple # but you could on your own if query.sort != [] || query.offset != 0 do {:error, "Cannot sort or offset documents"} end if query.sort && query.sort != [] do raise "Cannot apply a sort to docs read" end if query.offset && query.offset != 0 do raise "Cannot apply a sort to docs read" end limit = query.limit || :infinity query = Ash.Query.unset(query, :limit) query_results = Stream.resource( fn -> {limit, 0} end, fn {remaining, page_number} when remaining <= 0 -> {:halt, {0, page_number}} {remaining, page_number} -> api_results = query.arguments.query |> get!(page_number) |> Enum.map(&to_doc/1) case Ash.Query.apply_to(query, api_results) do {:ok, []} -> {:halt, remaining} {:ok, results} -> count_of_results = Enum.count(results) cond do # the api gives us batches of 100 remaining == :infinity && count_of_results == 100 -> {results, {:infinity, page_number + 1}} remaining == :infinity -> {results, {0, page_number + 1}} true -> still_remaining = remaining - count_of_results results = if still_remaining <= 0 do Enum.take(results, remaining) else results end {results, {still_remaining, page_number + 1}} end {:error, error} -> raise Ash.Error.to_ash_error(error) end end, fn _ -> :ok end ) |> Enum.to_list() {:ok, query_results} end defp to_doc(api_doc) do %Doc{author_name: api_doc["author_name"], type: api_doc["type"], title: api_doc["title"]} end defp get!(query, page) do params = if page == 0 do [q: query] else [q: query, page: page] end Req.get!("https://openlibrary.org/search.json", params: params).body["docs"] end end ``` ``` {:module, Doc.Actions.Read, <<70, 79, 82, 49, 0, 0, 25, ...>>, {:get!, 2}} ``` ## [](wrap-external-apis.html#now-we-can-use-this-like-any-other-ash-resource)Now we can use this like any other Ash resource ``` Domain.search!("Lord of the rings") ``` ``` [ #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "The Lord of the Rings", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "The Fellowship of the Ring", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "The Two Towers", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "The Return of the King", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "The Lord of the Rings", type: "work", aggregates: %{}, calculations: %{}, ... > ] ``` ``` require Ash.Query query = Doc |> Ash.Query.filter(contains(title, "Two")) Domain.search!("Lord of the rings", query: query) ``` ``` [ #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "The Two Towers", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["Alessio Cavatore", "Rick Priestley"], title: "The Lord of the Rings - The Two Towers", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "The Two Towers", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["Alessio Cavatore", "Rick Priestley"], title: "The Lord of the Rings - The Two Towers", type: "work", aggregates: %{}, calculations: %{}, ... >, #Doc< __meta__: #Ecto.Schema.Metadata<:built, "">, id: nil, author_name: ["J.R.R. Tolkien"], title: "Two Towers : The Lord of the Rings", type: "work", aggregates: %{}, calculations: %{}, ... > ] ``` [← Previous Page Prevent concurrent writes](prevent-concurrent-writes.html) [Next Page → Upgrade](upgrade.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/how-to/wrap-external-apis.livemd)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir") [![ash](assets/logo.png)](https://github.com/ash-project/ash) [ash](https://github.com/ash-project/ash) v3.4.58 Search documentation of ash Settings # Writing Extensions [View Source](https://github.com/ash-project/ash/blob/v3.4.58/documentation/topics/advanced/writing-extensions.md#L1 "View Source") Extensions allow you to make powerful modifications to DSL entities. If you are using `AshPostgres`, `AshGraphql` or `AshJsonApi`, they are all integrated into Ash using extensions. In this guide we will build a simple extension for [`Ash.Resource`](Ash.Resource.html) that adds timestamps to your resource. We'll also show some simple patterns that can help ensure that all of your resources are using your extension. ## [](writing-extensions.html#creating-an-extension)Creating an extension What we call an "extension" is typically one or more [`Spark.Dsl.Extension`](../spark/2.2.40/Spark.Dsl.Extension.html), and then any additional code that is used by that extension. For example, `AshGraphql` has a domain extension called `AshGraphql.Domain`, a resource extension called `AshGraphql.Resource`, and code to connect a GraphQL schema to your resources. ### [](writing-extensions.html#dsl-extension)DSL Extension Here we create a DSL extension called `MyApp.Extensions.Base`, and configure a single transformer, called `MyApp.Extensions.Base.AddTimestamps` ``` defmodule MyApp.Extensions.Base do use Spark.Dsl.Extension, transformers: [MyApp.Extensions.Base.AddTimestamps] end ``` ### [](writing-extensions.html#transformers)Transformers Transformers are all run serially against a map of data called `dsl_state`, which is the data structure that we build as we use the DSL. For example: ``` attributes do attribute :name, :string end ``` Would, under the hood, look something like this: ``` %{ [:attributes] => %{entities: [ %Ash.Resource.Attribute{name: :name, type: :string} ] }, ... } ``` A transformer exposes `transform/1`, which takes the `dsl_state` and returns either `{:ok, dsl_state}` or `{:error, error}` ``` defmodule MyApp.Extensions.Base.AddTimestamps do use Spark.Dsl.Transformer alias Spark.Dsl.Transformer def transform(dsl_state) do dsl_state # Ash.Resource.Builder has utilities for extending resources |> Ash.Resource.Builder.add_new_create_timestamp(:inserted_at) |> Ash.Resource.Builder.add_new_update_timestamp(:updated_at) end end ``` This transformer builds adds a `create_timestamp` called `:inserted_at` and an `update_timestamp` called `:updated_at`, unless they already exist. ### [](writing-extensions.html#make-the-extension-configurable)Make the extension configurable So far we've covered transformers, and using them to modify resources, but now lets say we want to make this behavior opt-out. Perhaps certain resources really shouldn't have timestamps, but we want it to be the default. Lets add a "DSL Section" to our extension. ``` defmodule MyApp.Extensions.Base do @base %Spark.Dsl.Section{ name: :base, describe: """ Configure the behavior of our base extension. """, examples: [ """ base do timestamps? false end """ ], schema: [ timestamps?: [ type: :boolean, doc: "Set to false to skip adding timestamps", default: true ] ] } use Spark.Dsl.Extension, transformers: [MyApp.Extensions.Base.AddTimestamps], sections: [@base] end defmodule MyApp.Extensions.Base.Info do use Spark.InfoGenerator, extension: MyApp.Extensions.Base, sections: [:base] # This will define `base_timestamps?/1`. end ``` Now we can use this configuration in our transformer, like so: ``` def transform(dsl_state) do # Introspection functions can take a `dsl_state` *or* a module if MyApp.Extensions.Base.Info.base_timestamps?(dsl_state) do dsl_state |> Ash.Resource.Builder.add_new_create_timestamp(:inserted_at) |> Ash.Resource.Builder.add_new_update_timestamp(:updated_at) else {:ok, dsl_state} end end ``` And now we have a configurable base extension! For more information on writing DSLs, see [`Spark`](../spark/2.2.40/Spark.html). [`Spark`](../spark/2.2.40/Spark.html) is still lacking in documentation, unfortunately, as its something that mostly the adventurous/power users work with, and they often learn by way of examples, looking at [`Ash`](Ash.html) extensions. We would like to rectify this in the future. Please reach out if you're interested in assisting with that effort! ### [](writing-extensions.html#ordering-of-transformers)Ordering of transformers In this case, this transformer can run in any order. However, as we start adding transformers and/or modify the behavior of this one, we may need to ensure that our transformer runs before or after specific transformers. As of the writing of this guide, the best way to look at the list of transformers is to look at the source of the extension, and see what transformers it has and what they do. The [Resource DSL](https://github.com/ash-project/ash/blob/main/lib/ash/resource/dsl.ex) for example. If you need to affect the ordering, you can define `before?/1` and `after?/1` in your transformer, i.e ``` # I go after every transformer def after?(_), do: true # except I go before `SomeOtherTransformer` def before?(SomeOtherTransformer), do: true def before?(_), do: false ``` ## [](writing-extensions.html#using-your-extension)Using your extension Now it can be used in a resource: ``` defmodule MyApp.Tweet do use Ash.Resource, extensions: [MyApp.Extensions.Base] base do # And you can configure it like so timestamps? false end end ``` Your extension will automatically support autocompletion if using `ElixirLS`, showing inline documentation and type-aware auto complete as you type. For more, see [Development Utilities](development-utilities.html) [← Previous Page Multitenancy](multitenancy.html) [Next Page → Define Polymorphic Relationships](polymorphic-relationships.html) [Hex Package](https://hex.pm/packages/ash/3.4.58) [Hex Preview](https://preview.hex.pm/preview/ash/3.4.58) ([current file](https://preview.hex.pm/preview/ash/3.4.58/show/documentation/topics/advanced/writing-extensions.md)) Search HexDocs [Download ePub version](ash.epub "ePub version") Built using [ExDoc](https://github.com/elixir-lang/ex_doc "ExDoc") (v0.37.0-rc.0) for the [Elixir programming language](https://elixir-lang.org "Elixir")

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/M-Gonzalo/cosa-sai'

If you have feedback or need assistance with the MCP directory API, please join our Discord server