mirror of
https://github.com/ash-project/ash_state_machine.git
synced 2024-09-20 13:23:52 +12:00
7f80527f51
closes #16
57 lines
1.5 KiB
Elixir
57 lines
1.5 KiB
Elixir
defmodule AshStateMachine.BuiltinChanges.TransitionState do
|
|
@moduledoc false
|
|
use Ash.Resource.Change
|
|
|
|
def change(changeset, opts, _) do
|
|
AshStateMachine.transition_state(changeset, opts[:target])
|
|
end
|
|
|
|
def atomic(changeset, opts, _) do
|
|
transitions =
|
|
AshStateMachine.Info.state_machine_transitions(changeset.resource, changeset.action.name)
|
|
|
|
attribute = AshStateMachine.Info.state_machine_state_attribute!(changeset.resource)
|
|
old_state = expr(^ref(attribute))
|
|
target = opts[:target]
|
|
|
|
all_states = AshStateMachine.Info.state_machine_all_states(changeset.resource)
|
|
|
|
states_expr =
|
|
Enum.reduce(transitions, nil, fn transition, expr ->
|
|
state_expr =
|
|
expr(^old_state in ^List.wrap(transition.from) and ^target in ^List.wrap(transition.to))
|
|
|
|
if is_nil(expr) do
|
|
state_expr
|
|
else
|
|
expr(state_expr or ^expr)
|
|
end
|
|
end)
|
|
|
|
new_state_value =
|
|
expr(
|
|
cond do
|
|
^target not in ^all_states ->
|
|
error(
|
|
AshStateMachine.Errors.NoMatchingTransition,
|
|
%{old_state: ^old_state, target: ^target, action: ^changeset.action.name}
|
|
)
|
|
|
|
^states_expr ->
|
|
^opts[:target]
|
|
|
|
true ->
|
|
error(
|
|
AshStateMachine.Errors.NoMatchingTransition,
|
|
%{
|
|
old_state: ^old_state,
|
|
target: ^target,
|
|
action: ^changeset.action.name
|
|
}
|
|
)
|
|
end
|
|
)
|
|
|
|
{:atomic, %{attribute => new_state_value}}
|
|
end
|
|
end
|