state_machine

State Machine implementation in Elixir. It's a structure and optionally a gen_statem powered process. It validates states and transitions for integrity and features seamless Ecto-integration.


License
MIT

Documentation

StateMachine

Build Status

StateMachine package implements state machine abstraction. It supports Ecto out of the box and can work as both data structure and a process powered by gen_statem.

Check out the article for motivation.

Here's an example of a simple state machine created with this package:

defmodule Cat do
  use StateMachine

  defstruct [:name, :state, hungry: true]

  defmachine field: :state do
    state :asleep
    state :awake
    state :playing
    state :eating, after_enter: &Cat.feed_up/1

    event :wake do
      transition from: :asleep, to: :awake
    end

    event :give_a_mouse do
      transition from: :awake, to: :playing, unless: &Cat.hungry/1
      transition from: :awake, to: :eating, if: &Cat.hungry/1
      transition from: :playing, to: :eating
    end

    event :pet do
      transition from: [:eating, :awake], to: :playing
    end

    event :sing_a_lullaby do
      transition from: :awake, to: :asleep
      transition from: :playing, to: :asleep
    end
  end

  def hungry(cat) do
    cat.hungry
  end

  def feed_up(cat) do
    {:ok, %{cat | hungry: false}}
  end
end

And later use it like this:

cat = %Cat{name: "Thomas", state: :asleep}

{:ok, %Cat{state: :awake}} = Cat.trigger(cat, :wake)

Features

  • Validation of state machine definition at compile time
  • Full support for callbacks (on states, events and transitions) and guards (on events and transitions)
  • Optional payload can be supplied with the event
  • One-line conversion to a state machine as a process (powered by gen_statem)
  • With Ecto support activated every transition is wrapped in transaction
  • With Ecto support activated the Ecto.Type implementation is generated automatically

Installation

The package can be installed by adding state_machine to your list of dependencies in mix.exs:

def deps do
  [
    {:state_machine, "~> 0.1"}
  ]
end

The documentation can be found at https://hexdocs.pm/state_machine.