Packages

ash

2.4.18
3.29.3 3.29.2 3.29.1 3.29.0 3.28.0 3.27.8 3.27.7 3.27.6 3.27.5 3.27.4 3.27.3 3.27.2 3.27.1 3.27.0 3.26.0 3.25.2 3.25.1 3.25.0 retired 3.24.7 3.24.6 3.24.5 3.24.4 3.24.3 3.24.2 3.24.1 3.24.0 3.23.1 3.23.0 3.22.2 3.22.1 3.22.0 3.21.3 3.21.2 3.21.1 3.21.0 3.20.0 3.19.3 3.19.2 3.19.1 3.19.0 3.18.0 3.17.1 3.17.0 3.16.0 3.15.0 3.14.1 3.14.0 retired 3.13.2 3.13.1 3.13.0 3.12.0 3.11.3 3.11.2 3.11.1 3.11.0 3.10.1 3.10.0 3.9.0 3.8.0 3.7.6 3.7.5 3.7.4 3.7.3 3.7.2 3.7.1 3.7.0 retired 3.6.3 retired 3.6.2 3.6.1 3.6.0 3.5.43 3.5.42 3.5.41 3.5.40 3.5.39 3.5.38 3.5.37 3.5.36 3.5.35 3.5.34 3.5.33 3.5.32 3.5.31 3.5.30 3.5.29 3.5.28 3.5.27 3.5.26 3.5.25 3.5.24 3.5.23 3.5.22 3.5.21 3.5.20 3.5.19 3.5.18 3.5.17 3.5.16 3.5.15 3.5.14 3.5.13 3.5.12 3.5.11 3.5.10 3.5.9 3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.74 retired 3.4.73 3.4.72 3.4.71 3.4.70 3.4.69 3.4.68 3.4.67 3.4.66 3.4.65 3.4.64 3.4.63 3.4.62 3.4.61 3.4.60 3.4.59 3.4.58 3.4.57 3.4.56 3.4.55 3.4.54 3.4.53 3.4.52 3.4.51 3.4.50 3.4.49 3.4.48 3.4.47 3.4.46 3.4.45 3.4.44 3.4.43 3.4.42 3.4.41 3.4.40 3.4.39 3.4.38 3.4.37 3.4.36 3.4.35 3.4.34 3.4.33 3.4.32 3.4.31 3.4.30 3.4.29 3.4.28 3.4.27 3.4.26 3.4.25 3.4.24 3.4.23 3.4.22 3.4.21 3.4.20 3.4.19 3.4.18 3.4.17 3.4.16 3.4.15 3.4.14 3.4.13 3.4.12 3.4.11 3.4.10 3.4.9 3.4.8 3.4.7 3.4.6 3.4.5 3.4.4 3.4.3 3.4.2 3.4.1 3.4.0 3.3.3 3.3.2 3.3.1 3.3.0 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 3.2.0 3.1.8 3.1.7 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.16 3.0.15 3.0.14 3.0.13 3.0.12 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.4 3.0.3 3.0.2 3.0.1 3.0.0 3.0.0-rc.46 3.0.0-rc.45 3.0.0-rc.44 3.0.0-rc.43 3.0.0-rc.42 3.0.0-rc.41 3.0.0-rc.40 3.0.0-rc.39 3.0.0-rc.38 3.0.0-rc.37 3.0.0-rc.36 3.0.0-rc.35 3.0.0-rc.34 3.0.0-rc.33 3.0.0-rc.32 3.0.0-rc.31 3.0.0-rc.29 3.0.0-rc.28 3.0.0-rc.27 3.0.0-rc.26 3.0.0-rc.25 3.0.0-rc.24 3.0.0-rc.23 3.0.0-rc.22 3.0.0-rc.21 3.0.0-rc.20 3.0.0-rc.19 3.0.0-rc.18 3.0.0-rc.17 3.0.0-rc.16 3.0.0-rc.15 3.0.0-rc.14 3.0.0-rc.13 3.0.0-rc.12 3.0.0-rc.11 3.0.0-rc.10 3.0.0-rc.9 3.0.0-rc.8 3.0.0-rc.7 3.0.0-rc.6 3.0.0-rc.5 3.0.0-rc.4 3.0.0-rc.3 3.0.0-rc.1 3.0.0-rc.0 2.21.15 2.21.14 2.21.13 2.21.12 2.21.11 2.21.10 2.21.9 2.21.8 2.21.7 2.21.6 2.21.5 2.21.4 2.21.3 2.21.2 2.21.1 2.21.0 2.20.3 2.20.2 2.20.1 2.20.0 2.19.14 2.19.13 2.19.12 2.19.11 2.19.10 2.19.9 2.19.8 2.19.7 2.19.6 2.19.5 2.19.4 2.19.3 retired 2.19.2 retired 2.19.1 retired 2.19.0 retired 2.18.2 2.18.1 2.18.0 2.17.24 2.17.23 2.17.22 2.17.21 2.17.20 2.17.19 2.17.18 2.17.17 2.17.16 2.17.15 2.17.14 2.17.13 2.17.12 2.17.11 2.17.10 2.17.9 2.17.8 2.17.7 2.17.6 2.17.5 2.17.4 2.17.3 2.17.2 2.17.1 2.17.0 2.16.1 2.16.0 2.15.20 2.15.19 2.15.18 2.15.17 2.15.16 2.15.15 2.15.14 2.15.13 2.15.12 2.15.11 2.15.10 2.15.9 2.15.8 2.15.7 2.15.6 2.15.5 2.15.4 2.15.2 2.15.1 2.15.0 2.14.21 2.14.20 2.14.19 2.14.18 2.14.17 2.14.16 2.14.15 2.14.14 2.14.13 2.14.12 2.14.11 2.14.10 2.14.9 2.14.8 2.14.7 2.14.6 2.14.5 2.14.4 2.14.3 2.14.2 2.14.1 2.14.0 2.13.4 retired 2.13.3 2.13.2 2.13.1 2.13.0 2.12.1 2.12.0 2.11.11 2.11.10 2.11.9 2.11.8 2.11.7 2.11.6 2.11.5 2.11.4 2.11.3 2.11.2 2.11.1 2.11.0 2.11.0-rc.3 2.11.0-rc.2 2.11.0-rc.1 2.11.0-rc.0 2.10.2 2.10.1 2.10.0 2.9.29 2.9.28 2.9.27 2.9.26 2.9.25 2.9.24 2.9.23 2.9.22 2.9.21 2.9.20 2.9.19 2.9.18 2.9.17 2.9.16 2.9.15 2.9.14 2.9.13 2.9.12 2.9.11 2.9.10 2.9.9 2.9.8 2.9.7 2.9.6 2.9.5 2.9.4 2.9.3 2.9.2 2.9.1 2.9.0 2.8.1 2.8.0 2.7.1 2.7.0 2.6.31 2.6.30 2.6.29 2.6.28 2.6.27 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.6.2 2.6.1 2.6.0 2.5.16 2.5.15 2.5.14 2.5.13 2.5.12 2.5.11 2.5.10 2.5.9 2.5.8 2.5.7 2.5.6 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5.0 2.5.0-rc.6 2.5.0-rc.5 2.5.0-rc.4 2.5.0-rc.3 2.5.0-rc.2 2.5.0-rc.1 2.5.0-rc.0 2.4.30 2.4.29 2.4.28 2.4.27 2.4.26 2.4.25 2.4.24 2.4.23 2.4.22 2.4.21 2.4.20 2.4.19 2.4.18 2.4.17 2.4.16 2.4.15 2.4.14 2.4.13 2.4.12 2.4.11 2.4.10 2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 2.0.0-rc.15 2.0.0-rc.14 2.0.0-rc.13 2.0.0-rc.12 2.0.0-rc.11 2.0.0-rc.10 2.0.0-rc.9 2.0.0-rc.8 2.0.0-rc.7 2.0.0-rc.6 2.0.0-rc.5 2.0.0-rc.4 2.0.0-rc.3 2.0.0-rc.2 2.0.0-rc.1 2.0.0-rc.0 2.0.0-pre.8 2.0.0-pre.7 2.0.0-pre.6 2.0.0-pre.5 2.0.0-pre.4 2.0.0-pre.3 2.0.0-pre.2 2.0.0-pre.1 2.0.0-pre.0 1.53.3 1.53.2 1.53.0 1.52.0-rc.22 1.52.0-rc.21 1.52.0-rc.20 1.52.0-rc.19 1.52.0-rc.18 1.52.0-rc.17 1.52.0-rc.16 1.52.0-rc.15 1.52.0-rc.14 1.52.0-rc.13 1.52.0-rc.12 1.52.0-rc.11 1.52.0-rc.10 1.52.0-rc.9 1.52.0-rc.8 1.52.0-rc.7 1.52.0-rc.6 1.52.0-rc.5 1.52.0-rc.4 1.52.0-rc.3 1.52.0-rc.2 1.52.0-rc.1 1.52.0-rc.0 1.51.2 1.51.1 retired 1.51.0 1.50.21 1.50.20 1.50.19 1.50.18 1.50.17 1.50.16 1.50.15 1.50.14 1.50.13 1.50.12 1.50.11 1.50.10 1.50.9 1.50.8 1.50.7 1.50.6 1.50.5 1.50.4 1.50.3 1.50.2 1.50.1 1.50.0 1.49.0 1.48.0-rc.30 1.48.0-rc.29 1.48.0-rc.28 1.48.0-rc.27 1.48.0-rc.26 1.48.0-rc.25 1.48.0-rc.24 1.48.0-rc.23 1.48.0-rc.22 1.48.0-rc.21 1.48.0-rc.20 1.48.0-rc.19 1.48.0-rc.18 1.48.0-rc.17 1.48.0-rc.16 1.48.0-rc.15 1.48.0-rc.14 1.48.0-rc.13 1.48.0-rc.12 1.48.0-rc.11 1.48.0-rc.10 1.48.0-rc.9 1.48.0-rc.8 1.48.0-rc.7 1.48.0-rc.6 1.48.0-rc.5 1.48.0-rc.4 1.48.0-rc.3 1.48.0-rc.2 1.48.0-rc.1 1.48.0-rc.0 1.47.12 1.47.11 1.47.10 1.47.9 1.47.8 1.47.7 1.47.6 1.47.5 1.47.4 1.47.3 1.47.2 1.47.1 1.47.0 1.46.13 1.46.12 1.46.11 1.46.10 1.46.9 1.46.8 1.46.7 1.46.6 1.46.5 1.46.4 1.46.3 1.46.2 1.46.1 1.46.0 1.45.0-rc9 1.45.0-rc8 1.45.0-rc7 1.45.0-rc6 1.45.0-rc5 1.45.0-rc4 1.45.0-rc3 1.45.0-rc20 1.45.0-rc2 1.45.0-rc19 1.45.0-rc18 1.45.0-rc17 1.45.0-rc16 1.45.0-rc15 1.45.0-rc14 1.45.0-rc13 1.45.0-rc12 1.45.0-rc11 1.45.0-rc10 1.45.0-rc1 1.45.0-rc0 1.44.13 1.44.12 1.44.11 1.44.10 1.44.9 1.44.8 1.44.7 1.44.6 1.44.5 1.44.4 1.44.3 1.44.2 1.44.1 1.44.0 1.43.12 1.43.11 1.43.10 1.43.9 1.43.8 1.43.7 1.43.6 1.43.5 1.43.4 1.43.3 1.43.2 1.43.1 1.43.0 1.42.0 1.41.12 1.41.11 1.41.10 1.41.9 1.41.8 1.41.7 1.41.6 1.41.5 1.41.4 1.41.3 1.41.2 1.41.1 1.41.0 1.40.0 1.39.7 1.39.6 1.39.5 1.39.4 1.39.3 1.39.2 1.39.1 1.39.0 1.38.0 1.37.2 1.37.1 1.37.0 1.36.22 1.36.21 1.36.19 1.36.18 1.36.17 1.36.16 1.36.15 1.36.14 1.36.13 1.36.12 1.36.11 1.36.10 1.36.9 1.36.8 1.36.7 1.36.6 1.36.5 1.36.4 1.36.3 1.36.2 1.36.0 1.35.1 1.35.0 1.34.9 1.34.8 1.34.7 1.34.6 1.34.5 1.34.4 1.34.3 1.34.2 1.34.1 1.34.0 1.33.0 1.32.2 1.32.1 1.32.0 1.31.1 1.31.0 1.30.2 1.30.1 1.29.0-rc1 1.29.0-rc0 1.28.1 1.28.0 1.27.1 1.27.0 1.26.13 1.26.12 1.26.11 1.26.10 1.26.9 1.26.8 1.26.7 1.26.6 1.26.5 1.26.4 1.26.2 1.26.1 1.26.0 1.25.8 1.25.7 1.25.6 1.25.5 1.25.4 1.25.3 1.25.2 1.25.1 1.25.0 1.24.2 1.24.1 1.24.0 1.23.3 1.23.2 1.23.1 1.23.0 1.22.1 1.22.0 1.20.1 1.20.0 1.19.1 1.19.0 1.18.1 1.18.0 1.17.1 1.17.0 1.16.2 1.15.1 1.15.0 1.14.0 1.13.4 1.13.3 1.13.2 1.13.1 1.13.0 1.12.0 1.11.1 1.11.0 1.10.0 1.9.0 1.8.0 1.7.0 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.1 1.5.0 1.4.1 1.4.0 1.3.1 1.3.0 1.2.1 1.2.0 1.1.3 1.1.2 1.1.0 1.0.3 1.0.2 1.0.1 1.0.0 0.13.1 0.13.0 0.12.0 0.10.0 0.9.1 0.9.0 0.8.0 0.7.0 0.6.5 0.6.4 0.6.3 0.6.2 0.6.1 0.6.0 0.5.2 0.5.1 0.5.0 0.4.0 0.3.0 0.2.0 0.1.9 0.1.8 0.1.3 0.1.1 0.1.0

A declarative, extensible framework for building Elixir applications.

Security advisory: This version has known vulnerabilities. View advisories

Current section

Files

Jump to
ash lib ash code_interface.ex
Raw

lib/ash/code_interface.ex

defmodule Ash.CodeInterface do
@moduledoc """
Used to define the functions of a code interface for a resource.
"""
@doc false
def require_action(resource, interface) do
action = Ash.Resource.Info.action(resource, interface.action || interface.name)
unless action do
raise Spark.Error.DslError,
module: resource,
message:
"The interface of #{inspect(resource)} refers to a non-existent action #{interface.action || interface.name}",
path: [:interfaces, :interface, interface.name]
end
action
end
@doc false
def default_value(resource, action, key) do
{field_type, field} =
case Enum.find(action.arguments, fn argument ->
argument.name == key
end) do
nil ->
{:attribute, Ash.Resource.Info.attribute(resource, key)}
argument ->
{:argument, argument}
end
if !field.allow_nil? do
raise "Code interface for #{action.name} has optional argument #{key} but it is not optional"
end
default =
if field_type == :argument do
field.default
else
if action.type == :update || (action.type == :destroy && action.soft?) do
if is_nil(action.update_default) do
field.default
else
field.update_default
end
else
field.default
end
end
if is_function(default) do
quote do
unquote(Macro.escape(default)).()
end
else
quote do
unquote(Macro.escape(default))
end
end
end
def without_optional(keys) do
Enum.map(keys, fn
{:optional, key} ->
key
key ->
key
end)
end
@doc """
Defines the code interface for a given resource + api combination in the current module. For example:
```elixir
defmodule MyApp.Accounting do
require Ash.CodeInterface
Ash.CodeInterface.define_interface(MyApp.Accounting, MyApp.Accounting.Transaction)
Ash.CodeInterface.define_interface(MyApp.Accounting, MyApp.Accounting.Account)
Ash.CodeInterface.define_interface(MyApp.Accounting, MyApp.Accounting.Invoice)
end
```
Keep in mind that you can have this "automatically" defined in your resources by using the `define_for`
flag in a resource.
For example:
```elixir
defmodule MyApp.Accounting.Transaction do
use Ash.Resource
...
code_interface do
define_for MyApp.Accounting
define :start do
args [:invoice_id]
end
end
end
# Which can now be used like so:
MyApp.Accounting.Transaction.start!(invoice.id)
```
"""
defmacro define_interface(api, resource) do
quote bind_quoted: [api: api, resource: resource], generated: true, location: :keep do
for interface <- Ash.Resource.Info.interfaces(resource) do
action = Ash.CodeInterface.require_action(resource, interface)
filter_keys =
if action.type == :read do
if interface.get_by_identity do
Ash.Resource.Info.identity(resource, interface.get_by_identity).keys
else
if interface.get_by do
interface.get_by
end
end
end
args = List.wrap(filter_keys) ++ Ash.CodeInterface.without_optional(interface.args || [])
arg_vars = Enum.map(args, &{&1, [], Elixir})
arg_vars_function =
filter_keys
|> List.wrap()
|> Enum.concat(interface.args || [])
|> Enum.map(fn
{:optional, key} ->
default = Ash.CodeInterface.default_value(resource, action, key)
{:\\, [], [{key, [], Elixir}, default]}
key ->
{key, [], Elixir}
end)
unless Enum.uniq(args) == args do
raise """
Arguments #{inspect(args)} for #{interface.name} are not unique!
"""
end
doc = """
#{action.description || "Calls the #{action.name} action on the #{inspect(resource)} resource."}
## Options
#{Spark.OptionsHelpers.docs(Ash.Resource.Interface.interface_options(action.type))}
"""
case action.type do
:read ->
@doc doc
@dialyzer {:nowarn_function, {interface.name, Enum.count(args) + 2}}
def unquote(interface.name)(
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(
__MODULE__,
elem(__ENV__.function, 0),
[
unquote_splicing(arg_vars_function),
%{},
params_or_opts
]
)
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
query =
if unquote(filter_keys) do
require Ash.Query
{filters, input} = Map.split(input, unquote(filter_keys))
opts[:query]
|> Kernel.||(unquote(resource))
|> Ash.Query.for_read(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
|> Ash.Query.filter(filters)
else
opts[:query]
|> Kernel.||(unquote(resource))
|> Ash.Query.for_read(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
end
if unquote(interface.get? || action.get?) do
query
|> unquote(api).read_one(
Keyword.drop(opts, [:query, :tenant, :authorize?, :actor])
)
|> case do
{:ok, nil} ->
if unquote(interface.not_found_error?) == false ||
Keyword.get(opts, :not_found_error?) == false do
{:ok, nil}
else
{:error, Ash.Error.Query.NotFound.exception(resource: query.resource)}
end
{:ok, result} ->
{:ok, result}
{:error, error} ->
{:error, error}
end
else
unquote(api).read(
query,
Keyword.drop(opts, [:query, :tenant, :actor, :authorize?])
)
end
end
end
@doc doc
# sobelow_skip ["DOS.BinToAtom"]
@dialyzer {:nowarn_function, {:"#{interface.name}!", Enum.count(args) + 2}}
def unquote(:"#{interface.name}!")(
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(
__MODULE__,
elem(__ENV__.function, 0),
[
unquote_splicing(arg_vars),
%{},
params_or_opts
]
)
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
query =
if unquote(filter_keys) do
require Ash.Query
{filters, input} = Map.split(input, unquote(filter_keys))
opts[:query]
|> Kernel.||(unquote(resource))
|> Ash.Query.for_read(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
|> Ash.Query.filter(filters)
else
opts[:query]
|> Kernel.||(unquote(resource))
|> Ash.Query.for_read(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
end
if unquote(interface.get? || action.get?) do
query
|> unquote(api).read_one!(
Keyword.drop(opts, [:query, :tenant, :authorize?, :actor])
)
|> case do
nil ->
if unquote(interface.not_found_error?) == false ||
Keyword.get(opts, :not_found_error?) == false do
nil
else
raise Ash.Error.Query.NotFound, resource: query.resource
end
result ->
result
end
else
unquote(api).read!(
query,
Keyword.drop(opts, [:query, :tenant, :actor, :authorize?])
)
end
end
end
:create ->
@doc doc
@dialyzer {:nowarn_function, {interface.name, Enum.count(args) + 2}}
def unquote(interface.name)(
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [
unquote_splicing(arg_vars),
%{},
params_or_opts
])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
opts[:changeset]
|> Kernel.||(unquote(resource))
|> Ash.Changeset.for_create(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
unquote(api).create(
changeset,
Keyword.drop(opts, [:actor, :changeset, :tenant, :authorize?, :tracer])
)
end
end
@doc doc
@dialyzer {:nowarn_function, {:"#{interface.name}!", Enum.count(args) + 2}}
# sobelow_skip ["DOS.BinToAtom"]
def unquote(:"#{interface.name}!")(
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [
unquote_splicing(arg_vars),
%{},
params_or_opts
])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
(opts[:changeset] || unquote(resource))
|> Ash.Changeset.for_create(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
unquote(api).create!(
changeset,
Keyword.drop(opts, [:actor, :changeset, :authorize?, :tracer])
)
end
end
:update ->
@doc doc
@dialyzer {:nowarn_function, {interface.name, Enum.count(args) + 3}}
def unquote(interface.name)(
record,
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [
record,
unquote_splicing(arg_vars),
%{},
params_or_opts
])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_update(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
unquote(api).update(
changeset,
Keyword.drop(opts, [:actor, :tenant, :authorize?, :tracer])
)
end
end
@doc doc
# sobelow_skip ["DOS.BinToAtom"]
@dialyzer {:nowarn_function, {:"#{interface.name}!", Enum.count(args) + 3}}
def unquote(:"#{interface.name}!")(
record,
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [
record,
unquote_splicing(arg_vars),
%{},
params_or_opts
])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_update(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
unquote(api).update!(
changeset,
Keyword.drop(opts, [:actor, :tenant, :authorize?, :tracer])
)
end
end
:destroy ->
@doc doc
@dialyzer {:nowarn_function, {interface.name, Enum.count(args) + 3}}
def unquote(interface.name)(
record,
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [
record,
unquote_splicing(arg_vars),
%{},
params_or_opts
])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_destroy(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
unquote(api).destroy(
changeset,
Keyword.drop(opts, [:actor, :tenant, :authorize?, :tracer])
)
end
end
@doc doc
# sobelow_skip ["DOS.BinToAtom"]
@dialyzer {:nowarn_function, {:"#{interface.name}!", Enum.count(args) + 3}}
def unquote(:"#{interface.name}!")(
record,
unquote_splicing(arg_vars_function),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [
record,
unquote_splicing(arg_vars),
%{},
params_or_opts
])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_destroy(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant, :authorize?, :tracer])
)
unquote(api).destroy!(
changeset,
Keyword.drop(opts, [:actor, :tenant, :authorize?, :tracer])
)
end
end
end
end
end
end
end