# Elixir Finite state machine
This package is inspired by [ecto_fsm](https://github.com/bluzky/ecto_fsm) package
This package allows to use [finite state machine pattern](https://en.wikipedia.org/wiki/Finite-state_machine) in elixir.
**Install**
```elixir
def deps do
[
{:as_fsm, "~> 0.1.0"}
]
end
```
## 1. Usage
Define your FSM
``` elixir
defmodule OrderState do
# define state, event and transition
use AsFsm,
states: [:new, :processing, :cancelled, :delivered],
events: [
confirm: [
name: "Confirm",
from: [:new],
to: :processing,
on_transition: (fn(model, params) ->
# do something
{:ok, model}
end),
on_enter: (fn(model, params) -> #do_something end),
guard: (fn(model, params) ->
# do some check here
true # return true to allow transition, false to abort
end)
],
deliver: [
name: "Deliver",
from: [:processing],
to: :delivered
],
cancel: [
name: "Cancel order",
from: [:new, :processing],
to: :cancelled,
on_transition: &update_stock/2
]
]
# define your callback function
def update_stock(model, params) do
# your code
end
end
```
**list all state**
```elixir
#> OrderState.states()
#> [:new, :processing, :cancelled, :delivered]
```
**list all event**
```elixir
#> OrderState.events()
#> [{:confirm, "Confirm"}, {:deliver, "Deliver"}, {:cancel, "Cancel Order"}]
```
**Check if can accept event**
```elixir
#> model = %{status: :new}
#> OrderState.can?(model, :confirm)
#> true
#> OrderState.can?(model, :cancel)
#> true
#> OrderState.can?(model, :deliver)
#> false
```
**Get accepted events**
All events that can used to trigger a transition
```elixir
#> model = %{status: :new}
#> OrderState.accepted_events(model)
#> [{:confirm, "Confirm"}, {:cancel, "Cancel order"}]
```
**Trigger an event**
```elixir
#> model = %{status: :new}
#> OrderState.confirm(model)
#> %{status: :processing}
#> # you can even pass data when trigger event
#> OrderState.confirm(model, %{message: "oke man"})
```
**Dynamic trigger event**
```elixir
#> model = %{status: :new}
#> OrderState.trigger(model, :confirm)
#> %{status: :processing}
#> # you can even pass data when trigger event
#> OrderState.trigger(model, :confirm, %{message: "oke man"})
```
## Options
- Custom property name
```elixir
defmodule ExampleFsm do
use AsFsm,
column: :state,
end
```