View Source Ash.CustomExpression behaviour (ash v3.0.8)
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 tofalse
.
Registering Your Expression
Use compile-time configuration to register your custom expressions
config :ash, :custom_expressions, [MyApp.Expressions.LevenshteinDistance]
Summary
Callbacks
@callback arguments() :: [[Ash.Type.t() | {Ash.Type.t(), Keyword.t()}]]
@callback expression( data_layer :: Ash.DataLayer.t(), arguments :: [Ash.Expr.t()] ) :: {:ok, Ash.Expr.t()} | :unknown
@callback name() :: atom()