mirror of
https://github.com/ash-project/ash.git
synced 2024-09-19 21:13:10 +12:00
improvement: support omitting generic action return types
This commit is contained in:
parent
a5074d9d2f
commit
bae263ca12
7 changed files with 40 additions and 7 deletions
|
@ -912,7 +912,7 @@ end
|
|||
|
||||
## actions.action
|
||||
```elixir
|
||||
action name, returns
|
||||
action name, returns \\ nil
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,20 @@ end
|
|||
|
||||
A generic action declares its arguments, return type, and implementation, as illustrated above.
|
||||
|
||||
> ### No return? No problem! {: .tip}
|
||||
>
|
||||
> Generic actions can omit a return type, in which case running them returns `:ok` if successful.
|
||||
>
|
||||
> ```elixir
|
||||
> action :schedule_job do
|
||||
> argument :job_name, :string, allow_nil?: false
|
||||
> run fn input ->
|
||||
> # Schedule the job
|
||||
> :ok
|
||||
> end
|
||||
> end
|
||||
> ```
|
||||
|
||||
## Why use generic actions?
|
||||
|
||||
The example above could be written as a normal function in elixir, i.e
|
||||
|
@ -51,7 +65,7 @@ action :priority, :integer do
|
|||
end
|
||||
```
|
||||
|
||||
> #### Returning resource instances {: .tip}
|
||||
> #### Returning resource instances {: .info}
|
||||
>
|
||||
> It sometimes happens that you want to make a generic action which returns an
|
||||
> instance or instances of the resource. It's natural to assume that you can
|
||||
|
|
|
@ -1261,7 +1261,7 @@ defmodule Ash do
|
|||
"""
|
||||
@doc spark_opts: [{1, @run_action_opts}]
|
||||
@spec run_action(input :: Ash.ActionInput.t(), opts :: Keyword.t()) ::
|
||||
{:ok, term} | {:error, Ash.Error.t()}
|
||||
:ok | {:ok, term} | {:error, Ash.Error.t()}
|
||||
def run_action(input, opts \\ []) do
|
||||
Ash.Helpers.expect_options!(opts)
|
||||
domain = Ash.Helpers.domain!(input, opts)
|
||||
|
|
|
@ -123,8 +123,15 @@ defmodule Ash.Actions.Action do
|
|||
case authorize(domain, opts[:actor], input) do
|
||||
:ok ->
|
||||
case call_run_function(module, input, run_opts, context, false) do
|
||||
:ok when is_nil(input.action.returns) ->
|
||||
:ok
|
||||
|
||||
{:ok, result} ->
|
||||
{:ok, result}
|
||||
if input.action.returns do
|
||||
{:ok, result}
|
||||
else
|
||||
:ok
|
||||
end
|
||||
|
||||
{:ok, result, notifications} ->
|
||||
remaining = Ash.Notifier.notify(notifications)
|
||||
|
@ -133,7 +140,11 @@ defmodule Ash.Actions.Action do
|
|||
resource_notifications: remaining
|
||||
})
|
||||
|
||||
{:ok, result}
|
||||
if input.action.returns do
|
||||
{:ok, result}
|
||||
else
|
||||
:ok
|
||||
end
|
||||
|
||||
{:error, error} ->
|
||||
{:error, error}
|
||||
|
|
|
@ -24,13 +24,17 @@ defmodule Ash.Resource.Actions.Action do
|
|||
touches_resources: [Ash.Resource.t()],
|
||||
constraints: Keyword.t(),
|
||||
run: {module, Keyword.t()},
|
||||
returns: Ash.Type.t(),
|
||||
returns: Ash.Type.t() | nil,
|
||||
primary?: boolean,
|
||||
transaction?: boolean
|
||||
}
|
||||
|
||||
import Ash.Resource.Actions.SharedOptions
|
||||
|
||||
def transform(%{returns: nil} = action) do
|
||||
{:ok, action}
|
||||
end
|
||||
|
||||
def transform(%{returns: original_type, constraints: constraints} = thing) do
|
||||
type = Ash.Type.get_type(original_type)
|
||||
|
||||
|
|
|
@ -495,7 +495,7 @@ defmodule Ash.Resource.Dsl do
|
|||
@action_argument
|
||||
]
|
||||
],
|
||||
args: [:name, :returns]
|
||||
args: [:name, {:optional, :returns}]
|
||||
}
|
||||
|
||||
@create %Spark.Dsl.Entity{
|
||||
|
|
|
@ -36,6 +36,10 @@ defmodule Ash.Test.Actions.GenericActionsTest do
|
|||
{:ok, "Hello #{input.arguments.name}"}
|
||||
end)
|
||||
end
|
||||
|
||||
action :do_nothing do
|
||||
run fn _ -> :ok end
|
||||
end
|
||||
end
|
||||
|
||||
attributes do
|
||||
|
|
Loading…
Reference in a new issue