simple_ecto_state_machine v0.1.0 SimpleEctoStateMachine

A simple state machine for Ecto Models. It works on the changeset of the model when the changeset is updated. When a state machine is used inside and Ecto model, a function of the form validate_{field}_update(changeset) is defined in the model, ready to test the changeset when is updated.

  defmodule MyModule do
    use Ecto.Model

    schema "my_module" do
      field :status
    end

    use SimpleEctoStateMachine,
      field: :status,
      transitions: [
        %{from: "status_a".  to: ["status_b, "status_c"]},
        %{from: "status_b", to: ["status_c"]}
      ]

    def changeset(model, params \ :empty) do
      model
        |> cast(params, ["status"], [])
        |> validate_status_update # <= Function defined by
                                  # SimpleEctoStateMachine at compile time.
    end
  end

Callbacks can be defined to be called in the case of success or error. Callbacks can be provided per destination. In case of a successful transition the callback with the form {to}_callback will be called. The error callback must be named state_machine_error_callback and will be called if a transition with a valid from is provided but the new value does not match any of the valid tos, i.e:

  def success_callback(_changeset) do
    IO.puts "Valid transition!"
  end

  def error_callback(_changeset) do
    IO.puts "Invalid transition."
  end

  use SimpleEctoStateMachine,
    field: status
    transitions: [
      %{
        from: "status_a",
        to: ["status_b, status_c"],
        status_a_callback: &__MODULE__.success_callback/1,
        status_b_callback: &__MODULE__.success_callback/1,
        error_callback: &__MODULE__.error.callback/1
      }
    ]

Make sure to only define one transition per from, since repeating froms lead to an error in the state machine. All possible transitions for a from must be defined in a single transition.

Summary

Functions

Translates the given transitions to a map. For example:

transitions = [
  %{from: "status_a", to: ["status_b"]},
  %{from: "status_b", to: ["status_a", "status_c"}]
]
parsed_transitions(transitions)
=> %{
  "status_a" => ["status_b"],
  "status_b" => ["status_a", "status_c"]
}

Functions

get_callback(from, to, transitions)
invalid_transition(from, to, field, transitions, changeset)
parse_transitions(transitions)

Translates the given transitions to a map. For example:

transitions = [
  %{from: "status_a", to: ["status_b"]},
  %{from: "status_b", to: ["status_a", "status_c"}]
]
parsed_transitions(transitions)
=> %{
  "status_a" => ["status_b"],
  "status_b" => ["status_a", "status_c"]
}
valid_transition(from, to, transitions, changeset)