Monthly Downloads: 7,277
Programming language: Elixir
License: Apache License 2.0
Latest version: v0.2.1

ecto_state_machine alternatives and similar packages

Based on the "State Machines" category

Do you think we are missing an alternative of ecto_state_machine or a related project?

Add another 'State Machines' Package


Ecto state machine

travis ci badge badge

This package allows to use finite state machine pattern in Ecto. Specify:

and go:

defmodule User do
  use Web, :model

  use EctoStateMachine,
    states: [:unconfirmed, :confirmed, :blocked, :admin],
    events: [
        name:     :confirm,
        from:     [:unconfirmed],
        to:       :confirmed,
        callback: fn(model) -> Ecto.Changeset.change(model, confirmed_at: Ecto.DateTime.utc) end # yeah you can bring your own code to these functions.
      ], [
        name:     :block,
        from:     [:confirmed, :admin],
        to:       :blocked
      ], [
        name:     :make_admin,
        from:     [:confirmed],
        to:       :admin

  schema "users" do
    field :state, :string, default: "unconfirmed"

now you can do:

user = Repo.get_by(User, id: 1)

# Create changeset transition user state to "confirmed". We can make him admin!
confirmed_user = User.confirm(user)     # =>

# We can validate ability to change user's state
User.can_confirm?(confirmed_user)       # => false
User.can_make_admin?(confirmed_user)    # => true

# Create changeset transition user state to "admin"
admin = User.make_admin(confirmed_user)

# Store changeset to the database

# List all possible states
# If column isn't `:state`, function name will be prefixed. IE,
# for column `:rules` function name will be `rules_states`
User.states # => [:unconfirmed, :confirmed, :blocked, :admin]

# List all possible events
# If column isn't `:state`, function name will be prefixed. IE,
# for column `:rules` function name will be `rules_events`
User.events # => [:confirm, :block, :make_admin]

You can check out whole test/dummy directory to inspect how to organize sample app.


If available in Hex, the package can be installed as:

  1. Add ecto_state_machine to your list of dependencies in mix.exs:

    def deps do
      [{:ecto_state_machine, "~> 0.1.0"}]

Custom column name

ecto_state_machine uses state database column by default. You can specify column option to change it. Like this:

defmodule Dummy.User do
  use Dummy.Web, :model

  use EctoStateMachine,
    column: :rules,
    # bla-bla-bla

Now your state will be stored into rules column.


  1. Install dependencies mix deps.get
  2. Setup your config/test.exs & config/dev.exs
  3. Run migrations mix ecto.migrate & MIX_ENV=test mix ecto.migrate
  4. Develop new feature
  5. Write new tests
  6. Test it: mix test
  7. Open new PR!

Roadmap to 1.0

  • [x] Cover by tests
  • [x] Custom db column name
  • [x] Validation method for changeset indicates its value in the correct range
  • [x] Initial value
  • [x] CI
  • [x] Add status? methods
  • [ ] Introduce it at elixir-radar and my blog
  • [ ] Custom error messages for changeset (with translations by gettext ability)
  • [x] Rely on last versions of ecto & elixir
  • [ ] Write dedicated module instead of requiring everything into the model
  • [ ] Write bang! methods which are raising exception instead of returning invalid changeset
  • [ ] Rewrite spaghetti description in README