Eventful
Eventful is a library for anyone who needs a trackable state machine. With transitions and triggers and guards.
Installation
If available in Hex, the package can be installed
by adding eventful to your list of dependencies in mix.exs:
def deps do
[
{:eventful, "~> 0.2.0"}
]
end
Current State
You will need to create a :current_state field in your model
schema "posts" do
field :current_state, :string, default: "draft"
end
# migration
alter table(:posts) do
field :current_state, :string, default: "draft", null: false
end
Event Schema
Generally your events table will be used to track events for a specific model you have Let's assume that in this case we have MyApp.Post and MyApp.User as the authenticated user in our app.
We may create something like this.
defmodule MyApp.Post.Event do
alias MyApp.{
Post,
User
}
use Eventful,
parent: {:post, Post},
actor: {:user, User}
end
Migration
Generate a migration file for your events like this.
defmodule MyApp.Repo.Migrations.CreatePostEvents do
use Ecto.Migration
def change do
create table(:post_events) do
add(:name, :string, null: false)
add(:domain, :string, null: false)
add(:metadata, :map, default: "{}")
add(
:post_id,
references(:posts, on_delete: :restrict),
null: false
)
add(
:user_id,
references(:users, on_delete: :restrict),
null: false
)
timestamps()
end
create(index(:post_events, [:post_id]))
create(index(:post_events, [:user_id]))
end
end
Transitions
The next thing is defining a Transitions module
defmodule MyApp.Post.Transitions do
alias MyApp.Post
@behaviour Eventful.Handler
use Eventful.Transition, repo: MyApp.Repo
Post
|> transition(
[from: "draft", to: "reviewing", via: "review"],
fn changes -> transit(changes) end)
)
Post
|> transition(
[from: "reviewing", to: "published", via: "publish"],
fn changes -> transit(changes) end)
)
end
Event Handler
You will now need to add the Transitions Handler to your Event module
defmodule MyApp.Post.Event do
alias MyApp.{
Post,
User
}
use Eventful,
parent: {:post, Post},
actor: {:user, User}
handle(:transitions, using: Post.Transitions)
end
Transitioning from State to State
MyApp.Post.Event.handle(post, user, %{domain: "transitions", name: "review"})
This will now transition and track your model and also track who did it.
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/eventful.