Ash 3.0 Teasers!

Ash 3.0 Teaser #5: Model your domain, derive the rest.

Code Interfaces on domain modules

When building APIs with Ash extensions, like AshGraphql and AshJsonApi, you are combining resource actions into a single interaction point. The code_interface tooling is a method for you to define a similar interaction point for your code. However, the general pattern encouraged defining functions that were called on each resource module. For example:

MyApp.Accounts.User.register_with_password(email, password)

However, this pattern often encourages “reaching in” to individual resources in your domain in your code, which can often make refactoring very difficult. For API extensions this is less of an issue because each action is exposed in such a way that it can have its implementation and backing resource modified in a way that is transparent to the caller (in some cases this is easier than in others).

However, in Elixir we’re used to encapsulating interfaces in a module designed for that purpose. To that end, in Ash 3.0 we now support specifying code interfaces on the domain, and in general we encourage this over defining code interfaces on the resource. Here is what it looks like:

defmodule MyApp.Accounts do
  use Ash.Domain

  resources do
    resource MyApp.Accounts.User do
      define :register_user, action: :register_with_password, args: [:username, :password]

With this definition, you’d have

MyApp.Accounts.register_user("username", "password")

This allows for defining the code-level interface for your action in one central place, and emphasizes the role of your domains as a central element for a given group of resources.

Policies on the domain

Authorization is an example of a cross cutting concern that we often want to apply in broad strokes across our application (not always, but sometimes). To this end, you can specify policies on the domain directly. When calling a resource, the policies from the relevant domain are included at the beginning of the list of policies for that resource. Then, authorization proceeds as normal.

The reason the domain policies go first is because of bypass policies. This allows you to do things like declare an admin bypass once in each domain, instead of each resource, or to define a policy like “deny inactive users” in the same way. For example:

defmodule MyApp.Accounts do
  use Ash.Domain,
    # note that it goes in `extensions`, not `authorizers`.
    extensions: [Ash.Policy.Authorizer]

  resources do
    resource MyApp.Accounts.User

  policies do
    bypass always() do
      authorize_if actor_attribute_equals(:admin, true)

    policy actor_attribute_equals(:active, false) do
      forbid_if always()

With this in place, any action calls to any resources using this domain will include these policies ahead of their own :partying_face:

The beginning of long term focus on DX & docs

During the remainder of the time before the 3.0 release, and while it is in release candidacy, we will be focusing on DX improvements and documentation. Some examples of these improvements actually come from the 2.0 release of another one of our packages, spark, which Ash 3.0 has been upgrade to support. Keep in mind that you have to be using ElixirLS (as it is based on elixir_sense) to get the benefits of our custom autocomplete extension.

Autocomplete options to use Ash.Resource

This actually applies to any spark DSL, but for Ash users this will most notably show when calling use Ash.Resource. For example:

Autocomplete of options for functions in Ash and generated code interface functions

Ash functions

Code Interface Functions

Additionally, code interface documentation has been updated to include any argument and accepted attribute descriptions. All together, this should drastically help with discoverability of what your code interface offers, and give you extremely high quality, well documented functions for interacting with your resources.


We’re getting closer and closer to the release candidate of Ash, but we’re already looking past that point. The experience that users have with Ash is extremely important to me, and I’m ecstatic that it is finally the right time to shift my efforts to these very important areas.

Until next time!

Teaser #6: Ash 3.0 Teasers! - #36 by zachdaniel