Skip to content

Commit

Permalink
Updating README and wrong docs
Browse files Browse the repository at this point in the history
  • Loading branch information
joaomdmoura committed Dec 13, 2017
1 parent df7d381 commit 415c79d
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 34 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## WIP Version

## 0.4.1
- Updating wrong docs and README - [Pull Request](https://github.com/joaomdmoura/machinery/pull/3)

## 0.4.0
- New, more functional DSL, not relying on Macros so much - [Pull Request](https://github.com/joaomdmoura/machinery/pull/1)
- Adding support for before and after callbacks - [Pull Request](https://github.com/joaomdmoura/machinery/pull/2)
Expand Down
60 changes: 37 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,28 @@ dependencies in `mix.exs`:
```elixir
def deps do
[
{:machinery, "~> 0.4.0"}
{:machinery, "~> 0.4.1"}
]
end
```

## Declaring States

Declare the states you need pasing it as an argment when importing `Machinery`
on the module that will control your states transitions.
Declare the states as an argment when importing `Machinery` on the module that
will control your states transitions.

Machinery expects a `Keyword` as argument with two keys `states` and `transitions`.

- `states`: A List of Atoms representing each state.
- `transitions`: A List of Maps, including two keys `from` and `to`, `to` might be an Atom or a List of Atoms.
- `transitions`: A Map for each state and it allowed next state(s).

### Example

```elixir
defmodule YourProject.UserStateMachine do
use Machinery,
# The first state declared will be considered the intial state
# The first state declared will be considered
# the intial state
states: [:created, :partial, :complete],
transitions: %{
created: [:partial, :complete],
Expand All @@ -59,13 +60,15 @@ end

## Changing States

To transit a struct into another state, you just need to call `Machinery.transition_to/2`
To transit a struct into another state, you just need to call `Machinery.transition_to/2`.

### `Machinery.transition_to/2`
It takes two arguments:

- `struct`: The struct you want to transit to another state
- `next_event`: An atom representing the next state you want the struct to transition to
- `struct`: The `struct` you want to transit to another state.
- `next_event`: An `atom` of the next state you want the struct to transition to.

**Guard functions, before and after callbacks will be checked automatically.**

```elixir
Machinery.transition_to(your_struct, :next_state)
Expand All @@ -79,26 +82,27 @@ user = Accounts.get_user!(1)
UserStateMachine.transition_to(user, :partial)
```

Guard functions, before and after callbacks will be checked automatically.

## Guard functions
Create guard conditions by adding signatures of the `guard_transition/2`
function, pattern matching the desired state you want to guard.

```elixir
def guard_transition(struct, :state), do: true
```

Guard conditions should return a boolean:
- `true`: Guard clause will allow the transition.
- `false`: Transition won't be allowed.

### Example:

```elixir
defmodule YourProject.UserStateMachine do
use Machinery,
# The first state declared will be considered the intial state
states: [:created, :partial, :complete],
transitions: %{
created: [:partial, :complete],
partial: :completed
}
states: [:created, :complete],
transitions: %{created: :complete}

# Guard the transition to the :complete state.
def guard_transition(struct, :complete) do
Map.get(struct, :missing_fields) == false
end
Expand All @@ -108,27 +112,37 @@ end
## Before and After callbacks

You can also use before and after callbacks to handle desired side effects and
reactions to a specific state transition, the implementation is pretty similar to
guard functions, you can just declare `before_transition/2` and ``after_transition/2`.
Before and After callbacks should return the struct being manipulated.
reactions to a specific state transition.

You can just declare `before_transition/2` and ` after_transition/2`,
pattern matching the desired state you want to.

**Make sure Before and After callbacks should return the struct.**

```elixir
# callbacks should always return the struct.
def before_transition(struct, :state), do: struct
def after_transition(struct, :state), do: struct
```

### Example:

```elixir
defmodule YourProject.UserStateMachine do
use Machinery,
# The first state declared will be considered the intial state
states: [:created, :partial, :complete],
transitions: %{
created: [:partial, :complete],
partial: :completed
}

def before_transition(struct, :partial) do
# ... overall desired side effect
def before_transition(struct, :partial) do
# ... overall desired side effects
struct
end

def after_transition(struct, :completed) do
# ... overall desired side effect
# ... overall desired side effects
struct
end
end
Expand Down
20 changes: 10 additions & 10 deletions lib/machinery.ex
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
defmodule Machinery do
@moduledoc """
Main Machinery module.
It keeps the bunk of the Machinery logics, it's the module that
will be imported with `use` on the module that the state machine will
be implemented.
It keeps the bunk of the Machinery logics, it's the module that will be
imported with `use` on the module that the state machine will be implemented.
The first state declared will be considered the intial state
## Parameters
- `opts`: A Keyword including `states` and `transitions`.
- `states`: A List of Atoms representing each state.
- `transitions`: A List of Maps, including two keys `from` and `to`, `to` might be an Atom or a List of Atoms.
- `transitions`: A Map for each state and it allowed next state(s).
## Example
```
defmodule Project.User do
use Machinery,
states: [:created, :partial, :complete],
transitions: [
%{from: :created, to: [:partial, :complete]},
%{from: :partal, to: :complete}
]
transitions: %{
created: [:partial, :complete],
partial: :completed
}
end
```
"""
Expand Down Expand Up @@ -54,9 +54,9 @@ defmodule Machinery do
end

@doc """
Triggers the transition of a struct to a new state if it passes the
Triggers the transition of a struct to a new state, if it passes any
existing guard clause, also runs any before or after callbacks.
It returns a tuple with `{:ok, state}`, or `{:error, "cause"}`.
It returns a tuple with `{:ok, struct}`, or `{:error, "reason"}`.
## Parameters
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Machinery.Mixfile do
def project do
[
app: :machinery,
version: "0.4.0",
version: "0.4.1",
elixir: "~> 1.5",
start_permanent: Mix.env == :prod,
deps: deps(),
Expand Down

0 comments on commit 415c79d

Please sign in to comment.