Search documentation of ash

# Ash.CustomExpression behaviour (ash v3.4.71)

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

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

### Registering Your Expression

Use compile-time configuration to register your custom expressions

    config :ash, :custom_expressions, [MyApp.Expressions.LevenshteinDistance]

# Summary

## Callbacks

arguments()
expression(data_layer, arguments)
name()

# Callbacks

# arguments()

    @callback arguments() :: [[Ash.Type.t() | {Ash.Type.t(), Keyword.t()}]]

# expression(data_layer, arguments)

    @callback expression(
      data_layer :: Ash.DataLayer.t(),
      arguments :: [Ash.Expr.t()]
    ) :: {:ok, Ash.Expr.t()} | :unknown

# name()

    @callback name() :: atom()