ash_state_machine/documentation/tutorials/getting-started-with-ash-state-machine.md

89 lines
2.1 KiB
Markdown
Raw Normal View History

2023-04-23 13:38:33 +12:00
# Getting Started with State Machines
## Get familiar with Ash resources
If you haven't already, read the [Ash Getting Started Guide](https://hexdocs.pm/ash/get-started.html), and familiarize yourself with Ash and Ash resources.
## Bring in the ash_state_machine dependency
```elixir
2024-07-14 08:17:20 +12:00
{:ash_state_machine, "~> 0.2.5"}
2023-04-23 13:38:33 +12:00
```
2024-05-06 01:35:11 +12:00
## Add the extension to your resource
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
```elixir
use Ash.Resource,
extensions: [AshStateMachine]
```
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
## Add initial states, and a default initial state
2023-04-23 13:38:33 +12:00
```elixir
2024-05-06 01:35:11 +12:00
use Ash.Resource,
extensions: [AshStateMachine]
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
...
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
state_machine do
2024-06-12 05:36:38 +12:00
initial_states [:pending]
default_initial_state :pending
2024-05-06 01:35:11 +12:00
end
```
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
## Add allowed transitions
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
```elixir
state_machine do
2024-06-12 05:36:38 +12:00
initial_states [:pending]
default_initial_state :pending
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
transitions do
# `:begin` action can move state from `:pending` to `:started`/`:aborted`
transition :begin, from: :pending, to: [:started, :aborted]
2023-04-23 13:38:33 +12:00
end
end
```
2024-05-06 01:35:11 +12:00
## Use `transition_state` in your actions
2024-05-06 01:35:11 +12:00
### For simple/static state transitions
```elixir
2024-05-06 01:35:11 +12:00
actions do
update :begin do
# for a static state transition
change transition_state(:started)
end
end
```
2024-05-06 01:35:11 +12:00
### For dynamic/conditional state transitions
2024-05-06 01:35:11 +12:00
```elixir
defmodule Start do
use Ash.Resource.Change
def change(changeset, _, _) do
if ready_to_start?(changeset) do
AshStateMachine.transition_state(changeset, :started)
else
AshStateMachine.transition_state(changeset, :aborted)
end
end
end
2023-04-23 13:38:33 +12:00
2024-05-06 01:35:11 +12:00
actions do
update :begin do
# for a dynamic state transition
change Start
end
end
2023-04-23 13:38:33 +12:00
```
2024-05-06 01:35:11 +12:00
## Making a resource into a state machine
2023-04-23 18:47:22 +12:00
2024-05-06 01:35:11 +12:00
The concept of a state machine (in this case a "Finite State Machine"), essentially involves a single `state`, with specified transitions between states. For example, you might have an order state machine with states `[:pending, :on_its_way, :delivered]`. However, you can't go from `:pending` to `:delivered` (probably), and so you want to only allow certain transitions in certain circumstances, i.e `:pending -> :on_its_way -> :delivered`.
This extension's goal is to help you write clear and clean state machines, with all of the extensibility and power of Ash resources and actions.