Skip to content

Commit

Permalink
Allow guard functions to return a custom error tuple
Browse files Browse the repository at this point in the history
  • Loading branch information
norbajunior committed Feb 11, 2023
1 parent da316b4 commit edff76e
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 11 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You can install `machinist` by adding it to your list of dependencies in `mix.e
```elixir
def deps do
[
{:machinist, "~> 2.1.0"}
{:machinist, "~> 2.2.0"}
]
end
```
Expand Down Expand Up @@ -104,11 +104,15 @@ transitions do
end

defp check_passcode(door) do
if some_condition, do: :unlocked, else: :locked
if some_condition do
:unlocked
else
{:error, "invalid passcode"}
end
end
```

So when we call `Door.transit(%Door{state: :locked}, event: "unlock")` the guard function `check_passcode/1` will be called with the struct door as the first parameter and returns the new state to be set.
So when we call `Door.transit(%Door{state: :locked}, event: "unlock")` the guard function `check_passcode/1` will be called with the struct door as the first parameter and returns the new state to be set or a transition error tuple.

### Setting a different attribute name that holds the state

Expand Down
7 changes: 4 additions & 3 deletions lib/machinist.ex
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,10 @@ defmodule Machinist do
quote do
@impl true
def transit(%@__struct__{@__attr__ => unquote(state)} = resource, event: unquote(event)) do
value = __set_new_state__(resource, unquote(new_state))

{:ok, Map.put(resource, @__attr__, value)}
case __set_new_state__(resource, unquote(new_state)) do
{:error, _msg} = term -> term
new_state -> {:ok, Map.put(resource, @__attr__, new_state)}
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/machinist/transition.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ defmodule Machinist.Transition do
`Machinist.Transition` module behaviour
"""
@callback transit(struct(), event: String.t()) ::
{:ok, struct()} | {:error, :not_allowed}
{:ok, struct()} | {:error, :not_allowed | String.t()}
end
4 changes: 2 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Machinist.MixProject do
use Mix.Project

@version "2.1.0"
@version "2.1.1"
@repo_url "https://github.com/norbajunior/machinist"

def project do
Expand All @@ -18,7 +18,7 @@ defmodule Machinist.MixProject do

# Docs
name: "Machinist",
description: "A tiny Elixir lib to write state machines",
description: "A small Elixir lib to write state machines",
docs: [
extras: ["README.md"],
main: "Machinist",
Expand Down
4 changes: 2 additions & 2 deletions test/machinist_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ defmodule MachinistTest do
end

defp check_status(%Example7{status: :in_progress}) do
:tests_in_progress
{:error, "The test is in progress yet."}
end
end

Expand Down Expand Up @@ -241,7 +241,7 @@ defmodule MachinistTest do
test "transits from test_in_progress to test_in_progress" do
example = %Example7{state: :tests_in_progress, status: :in_progress}

assert {:ok, %Example7{state: :tests_in_progress}} =
assert {:error, "The test is in progress yet."} =
Example7.transit(example, event: "update_test_score")
end
end
Expand Down

0 comments on commit edff76e

Please sign in to comment.