AshBackpex.Adapter (Ash Backpex v0.1.6)

View Source

The Backpex adapter implementation for Ash resources.

This module implements the Backpex.Adapter behaviour to bridge Backpex's admin interface operations with Ash Framework's resource system. It handles all CRUD operations, search, filtering, sorting, and pagination by translating Backpex requests into Ash queries and actions.

Automatic Usage

When you use AshBackpex.LiveResource, this adapter is automatically configured for you. You typically don't need to reference it directly:

defmodule MyAppWeb.Admin.PostLive do
  use AshBackpex.LiveResource

  backpex do
    resource MyApp.Blog.Post
    layout {MyAppWeb.Layouts, :admin}

    fields do
      field :title
      field :author
    end
  end
end

Key Features

CRUD Operations

The adapter translates Backpex operations to Ash actions:

Authorization

The adapter respects Ash authorization by passing the actor option (from assigns.current_user) to all Ash operations. This integrates with your Ash policies automatically.

Custom Actions

You can specify which Ash actions to use via the DSL or adapter config:

backpex do
  resource MyApp.Blog.Post
  layout {MyAppWeb.Layouts, :admin}

  create_action :admin_create
  read_action :admin_read
  update_action :admin_update
  destroy_action :soft_delete
end

If not specified, the primary action for each type is used.

Custom Changesets

For advanced control over creates and updates, provide custom changeset functions:

backpex do
  resource MyApp.Blog.Post
  layout {MyAppWeb.Layouts, :admin}

  create_changeset fn item, params, metadata ->
    assigns = Keyword.get(metadata, :assigns)
    target = Keyword.get(metadata, :target)

    Ash.Changeset.for_create(item.__struct__, :create, params,
      actor: assigns.current_user
    )
  end
end

The changeset function receives:

  • item - The struct being created/updated
  • params - The form parameters
  • metadata - Keyword list with :assigns and :target keys

Loads

Relationships, calculations, and aggregates are loaded automatically based on the fields you configure. Additional loads can be specified:

backpex do
  resource MyApp.Blog.Post
  layout {MyAppWeb.Layouts, :admin}
  load [:author, :comments, nested: [:author]]
end

Search and Filtering

Search is handled by AshBackpex.BasicSearch which applies contains filters on searchable fields. Filters from the Backpex UI are translated to Ash query filters automatically.

Sorting

Initial sorting is configurable via init_order:

backpex do
  resource MyApp.Blog.Post
  layout {MyAppWeb.Layouts, :admin}
  init_order %{by: :inserted_at, direction: :desc}
end

User-requested sorting from the UI is handled via query parameters.

Configuration Schema

  • :resource (atom/0) - Required. The Ash.Resource that will be used to perform CRUD operations.

  • :schema (atom/0) - Required. The Ash.Resource for the resource.

  • :repo (atom/0) - Required. The Ecto.Repo that will be used to perform CRUD operations for the given schema.

  • :create_action (atom/0) - The resource action to use when creating new items in the admin. Defaults to the primary create action.

  • :read_action (atom/0) - The resource action to use when reading items in the admin. Defaults to the primary read action.

  • :update_action (atom/0) - The resource action to use when updating items in the admin. Defaults to the primary update action.

  • :destroy_action (atom/0) - The resource action to use when destroying items in the admin. Defaults to the primary destroy action.

  • :create_changeset (function of arity 3) - Changeset to use when creating items. Additional metadata is passed as a keyword list via the third parameter:

    • :assigns - the assigns
    • :target - the name of the form target that triggered the changeset call. Default to nil if the call was not triggered by a form field. The default value is &AshBackpex.Adapter.create_changeset/3.
  • :update_changeset (function of arity 3) - Required. Changeset to use when updating items. Additional metadata is passed as a keyword list via the third parameter:

    • :assigns - the assigns
    • :target - the name of the form target that triggered the changeset call. Default to nil if the call was not triggered by a form field. The default value is &AshBackpex.Adapter.update_changeset/3.
  • :load (function of arity 3) - Relationships, calculations and aggregates that Ash should load

    • [comments: [:author]] The default value is &AshBackpex.Adapter.load/3.
  • :init_order - You can configure the ordering of the resource index page. By default, the resources are ordered by the primary key field in ascending order.

    • %{by: :inserted_at, direction: :desc} The default value is %{direction: :asc, by: :id}.

Summary

Functions

Applies a filter to the query using a filter module's to_ash_expr/3 callback.

Returns the number of items matching the given criteria.

Deletes multiple items.

Gets a database record with the given primary key value.

Inserts given item.

Returns a list of items by given criteria.

Updates given item.

Functions

apply_filter_with_module(query, field, value, module, assigns)

@spec apply_filter_with_module(Ash.Query.t(), atom(), any(), module(), map()) ::
  Ash.Query.t()

Applies a filter to the query using a filter module's to_ash_expr/3 callback.

This helper function is used when filters have an associated module that implements the AshBackpex.Filters.Filter behavior. The module's to_ash_expr/3 callback is invoked to generate an Ash.Expr expression, which is then applied to the query.

Parameters

  • query - The Ash.Query to apply the filter to
  • field - The atom name of the attribute being filtered
  • value - The filter value from the UI
  • module - The filter module implementing AshBackpex.Filters.Filter
  • assigns - The LiveView assigns map

Returns

The query with the filter applied, or the unchanged query if the filter module returns nil from to_ash_expr/3.

Example

iex> query = Ash.Query.new(MyResource)
iex> apply_filter_with_module(query, :published, ["true"], AshBackpex.Filters.Boolean, %{})
# Returns query with filter: published == true

change(item, attrs, fields, assigns, live_resource, opts)

Applies a change to a given item.

count(criteria, fields, assigns, live_resource)

@spec count(keyword(), keyword(), map(), module()) ::
  {:ok, [map()]} | {:error, term()}

Returns the number of items matching the given criteria.

create_changeset(item, params, assigns)

delete_all(items, live_resource)

Deletes multiple items.

get(primary_value, fields, assigns, live_resource)

@spec get(String.t(), keyword(), map(), module()) :: {:ok, [map()]} | {:error, term()}

Gets a database record with the given primary key value.

Returns nil if no result was found.

insert(changeset, live_resource)

Inserts given item.

list(criteria, fields, assigns, live_resource)

@spec list(keyword(), keyword(), map(), module()) :: {:ok, [map()]} | {:error, term()}

Returns a list of items by given criteria.

load(_, _, _)

update(changeset, live_resource)

Updates given item.

update_all(items, updates, live_resource)

Updates given items.

update_changeset(item, params, assigns)

validate_config!(config)