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"}
]
endCurrent 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
endEvent 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}
endMigration
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
endTransitions
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)
)
endEvent 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)
endTransitioning 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.