-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a02b6d3
commit 32e2ced
Showing
7 changed files
with
137 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Charts | ||
|
||
Run `mix ash_state_machine.generate_flow_charts` to generate flow charts for your resources. See the task documentation for more. Here is an example: | ||
|
||
```mermaid | ||
stateDiagram-v2 | ||
pending --> confirmed: confirm | ||
confirmed --> on_its_way: begin_delivery | ||
on_its_way --> arrived: package_arrived | ||
on_its_way --> error: error | ||
confirmed --> error: error | ||
pending --> error: error | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# What is AshStateMachine? | ||
|
||
## What is a State Machine? | ||
|
||
A state machine is a program who's purpose is to manage an internal "state". The simplest example of a state machine could be a program representing a light switch. A light switch might have two states, "on" and "off". You can transition from "on" to "off", and back. | ||
|
||
```mermaid | ||
classDiagram | ||
class Switch { | ||
state on | off | ||
turnOn() off -> on | ||
turnOff() on -> off | ||
} | ||
``` | ||
|
||
To build state machines with `Ash.Resource`, we use [`AshStateMachine`](https://hexdocs.pm/ash_state_machine). | ||
|
||
When we refer to "state machines" in AshStateMachine, we're referring to a specific type of state machine known as a "Finite State Machine". | ||
It is "finite", because there are a statically known list of states that the machine may be in at any time, just like the `Switch` example above. | ||
|
||
### Why should we use state machines? | ||
|
||
#### Flexible | ||
|
||
State machines are a _simple_ and _powerful_ way to represent complex workflows. They are flexible to modifications over time by adding new states, or new transitions between states. | ||
|
||
#### Migrateable | ||
|
||
State machines typically contain additional data about the state that they are in, or past states that they have been in, and this state must be migrated over time. When representing data as state machines, it becomes simple to do things like "update all `package` records that are in the `pending_shipment` state". | ||
|
||
#### Easy to reason about for humans | ||
|
||
State machines, when compared to things like workflows, are easy for people to reason about. We have an intuition for things like "the package is currently `on_its_way`, with a `current_location` of New York, New York", or "your package is now `out_for_delivery` with an ETA of 6PM". | ||
|
||
#### Compatible with any storage mechanism | ||
|
||
Since state machines are backed by simple state, you can often avoid any fancy workflow runners or complex storage mechanisms. You can store them in a database table, a json blob, a CSV file, at the end of the day its just a `:state` field and accompanying additional fields. | ||
|
||
## What does AshStateMachine do differently than other implementations? | ||
|
||
AshStateMachine is an [`Ash.Resource`](https://hexdocs.pm/ash/Ash.Resource.html) extension, meaning it _enhances a resource_ with state machine capabilities. In `Ash`, all modifications go through [_actions_](actions.html). In accordance with this, `AshStateMachine` offers a DSL for declaring _valid states and transitions_, but does not, itself, _perform_ those transitions. You will use a change called `transition_state/1` in an action to move from one state to the other. For more, check out the [CookBook](https://hexdocs.pm/ash/readme.html#cookbook) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Working with `Ash.can?` | ||
|
||
Using `Ash.can?/3` won't return `false` if a given state machine transition is invalid. This is because `Ash.can?/3` is only concerned with policies, not changes/validations. However, many folks use `Ash.can?/3` in their UI to determine whether a given button/form/etc should be shown. To help with this you can add the following to your resource: | ||
|
||
```elixir | ||
policies do | ||
policy always() do | ||
authorize_if AshStateMachine.Checks.ValidNextState | ||
end | ||
end | ||
``` | ||
|
||
This check is only used in _pre_flight_ authorization checks (i.e calling `Ash.can?/3`), but it will return `true` in all cases when running real authorization checks. This is because the change is validated when you use the `transition_state/1` change and `AshStateMachine.transition_state/2`, and so you would be doing extra work for no reason. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters