ash_state_machine/lib/builtin_changes/next_state.ex

41 lines
1.1 KiB
Elixir
Raw Normal View History

defmodule AshStateMachine.BuiltinChanges.NextState do
@moduledoc """
Given the action and the current state, attempt to find the next state to
transition into.
"""
use Ash.Resource.Change
def change(changeset, _opts, _) do
attribute = AshStateMachine.Info.state_machine_state_attribute!(changeset.resource)
current_state = Map.get(changeset.data, attribute)
changeset.resource
|> AshStateMachine.Info.state_machine_transitions(changeset.action.name)
|> Enum.filter(fn
%{from: from} when is_list(from) -> current_state in from || :* in from
%{from: :*} -> true
%{from: from} -> current_state == from
end)
|> Enum.flat_map(fn
%{to: to} when is_list(to) -> to
%{to: to} -> [to]
end)
|> Enum.uniq()
|> Enum.reject(&(&1 == :*))
|> case do
[to] ->
AshStateMachine.transition_state(changeset, to)
[] ->
Ash.Changeset.add_error(changeset, "Cannot determine next state: no next state available")
_ ->
Ash.Changeset.add_error(
changeset,
"Cannot determine next state: multiple next states available"
)
end
end
end