Cheatsheet

View Source

Use this cheatsheet to quickly lookup the APIs for XFsm.

Examples

Creating a state machine

defmodule ToggleMachine do
  use XFsm.Actor
  use XFsm.Machine

  initial(:active)
  context(%{count: 0})

  state :active do
    entry(assigns(%{count: &(&1.context.count +1)}))

    on :toggle, do: target(:inactive)
  end

  state :inactive do
    on :toggle, do: target(:active)
  end
end

alias XFsm.Actor

{:ok, pid} = ToggleMachine.start_link()

Actor.subscribe(pid, &IO.puts/1)

Actor.send(pid, %{type: :toggle})
# logs 'inactive' with context %{count: 1}

Actor.send(pid, %{type: :toggle})
# logs 'active' with context %{count: 2}

Actor.send(pid, %{type: :toggle})
# logs 'inactive' with context %{count: 2}

Guards

defmodule ToggleMachine do
  use XFsm.Actor
  use XFsm.Machine

  initial(:active)
  context(%{activate?: false})

  state :inactive do
    on :toggle do
      target(:active)
      guard(:toggle?)
    end

    on :toggle do
      action(:notify_not_allowed)
    end
  end

  state :active do
    on :toggle do
      target(:inactive)
      guard(%{
        method: :after_time?,
        params: %{time: "00:00"}
      })
    end
  end

  defg toggle?(%{context: context}), do: context.activate?

  defg after_time?(_, %{time: time}) do
    now = DateTime.utc_now()
    [hour, minute] = String.split(time, ":")
    {hour, ""} = Integer.parse(hour)
    {minute, ""} = Integer.parse(minute)

    now.hour > hour and now.minute > minute
  end

  defa notify_not_allowed(%{context: context}) do
    IO.puts("Cannot be toggled")
    context
  end
end

Actions

defmodule ToggleMachine do
  use XFsm.Actor
  use XFsm.Machine

  initial(:active)

  state :active do
    entry(:activate)
    exit(:deactivate)

    on :toggle do
      target(:inactive)
      action(:notify)
    end
  end

  state :inactive do
    on :toggle do
      target(:active)
      action(%{
        method: :notify,
        params: %{message: "Some notification"}
      })
    end
  end

  defa activate(_) do
    # ...
  end

  defa deactivate(_) do
    # ...
  end

  defa notify(_,  %{message: _}) do
    # ...
  end
end