Search documentation of ash

# View Source Domains

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
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, you can think of a domain as the Ash equivalent.

## Grouping Resources

In an `Ash.Domain`, 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]

## Centralized Code Interface

Working with our domain & resources in code can be done the long form way, by building changesets/queries/action inputs and calling the relevant function in `Ash`. 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)

## Configuring Cross-cutting Concerns

### Built in configuration

`Ash.Domain` 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

### 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

### Policies

You can also use `Ash.Policy.Authorizer` 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 Changelog
Next Page → Attributes