Ash is a declarative, extensible framework for building Elixir applications. It provides a resource-oriented programming model where you define your application's data structures, business logic, and behaviors using a Domain-Specific Language (DSL), and Ash handles the execution, authorization, validation, and persistence concerns.
This page introduces the fundamental concepts and architecture of Ash. For step-by-step instructions on building your first Ash application, see Getting Started. For detailed information about specific subsystems, see the child pages under this Overview section.
Ash operates on the principle of declarative resource definitions. Rather than writing imperative code for CRUD operations, you declare:
Ash.Resource with attributes)actions)relationships)Ash.Policy.Authorizer)Ash.DataLayer.Ets, AshPostgres, etc.)The framework then provides a consistent interface for working with these resources through modules like Ash, Ash.Query, and Ash.Changeset.
Sources: mix.exs9-11 README.md1-22 lib/ash.ex1-8
Diagram: Ash Framework Component Relationships
The framework consists of three primary layers:
Ash.Resource modules define data structures, actions, and behaviorsAsh.Changeset, Ash.Query, and Ash.ActionInput structures prepare operations; the Ash module executes themAsh.DataLayer implementations handle persistenceSources: lib/ash/resource.ex5-10 lib/ash.ex5-8 documentation/tutorials/get-started.md106-153
A resource is a module that uses Ash.Resource and defines a data entity. Resources declare:
attributes DSL block)belongs_to, has_many, etc.)create, read, update, destroy, action)Sources: lib/ash/resource.ex1-24 documentation/tutorials/get-started.md119-179
A domain is a module that uses Ash.Domain and groups related resources together. Domains serve as the entry point for interacting with resources and define which resources are available in a given context.
Domains must be registered in your application configuration:
Sources: documentation/tutorials/get-started.md145-153 documentation/tutorials/get-started.md196-200 lib/ash/resource.ex72-117
Diagram: Action Execution Flow with Code Entities
Actions in Ash follow a consistent pattern:
Ash.Changeset (for mutations), Ash.Query (for reads), or Ash.ActionInput (for generic actions)Ash module functionExample:
Sources: documentation/tutorials/get-started.md206-223 documentation/tutorials/get-started.md281-300 lib/ash.ex1-8
Ash includes a comprehensive type system for attributes and arguments. All types implement the Ash.Type behavior.
| Category | Examples | Module Path |
|---|---|---|
| Primitives | :string, :integer, :boolean, :float, :atom | Ash.Type.* |
| Temporal | :date, :datetime, :time, :duration | Ash.Type.Date, etc. |
| Special | :uuid, :map, :term | Ash.Type.UUID, etc. |
| Collections | {:array, type} | Ash.Type with constraints |
| Custom | Embedded resources, unions, newtypes | Ash.Resource, Ash.Type.Union |
Types define how values are:
cast_input/3)apply_constraints/2)dump_to_native/2)cast_stored/2)Sources: lib/ash/resource.ex1-24 mix.exs references to type modules
Ash's extension system allows you to add functionality to resources through extensions. Extensions use the Spark DSL framework to add new configuration options.
Diagram: Extension Architecture
Data Layers implement the Ash.DataLayer behavior and handle persistence:
Ash.DataLayer.Ets - In-memory storage using Erlang Term StorageAsh.DataLayer.Mnesia - Distributed in-memory storageAsh.DataLayer.Simple - No persistence (for testing/static data)AshPostgres.DataLayer, AshSqlite.DataLayer - External packages for databasesAuthorizers implement the Ash.Authorizer behavior and control access:
Ash.Policy.Authorizer - Declarative policy-based authorization using a SAT solverNotifiers implement the Ash.Notifier behavior and react to changes:
Ash.Notifier.PubSub - Phoenix.PubSub integration for broadcasting eventsSources: lib/ash/resource.ex15-29 mix.exs56-63 README.md142-148
The Ash.Query module provides a fluent interface for building queries with filters, sorts, and data loading.
Diagram: Query Building API
Example queries:
Filters are parsed into expression trees (see Ash.Filter) that can be:
Ash.Filter.Runtime (fallback)Sources: documentation/tutorials/get-started.md423-460 lib/ash.ex88-151
Resources can generate code interfaces for ergonomic access. This is done through the code_interface DSL section:
This generates functions like:
MyApp.Ticket.open!(subject)MyApp.Ticket.close!(ticket)MyApp.Ticket.list!()Sources: lib/ash/resource.ex294-304 README.md89 documentation/tutorials/get-started.md666-669
Here's a minimal working example showing the core concepts:
Sources: documentation/tutorials/get-started.md119-300
Sources: README.md23-122 documentation/tutorials/get-started.md1-670 mix.exs1-449
Refresh this wiki
This wiki was recently refreshed. Please wait 7 days to refresh again.