Skip to content

Commit

Permalink
Setting up docs
Browse files Browse the repository at this point in the history
  • Loading branch information
naps62 committed Jun 25, 2020
1 parent bc132e3 commit 047ed49
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 9 deletions.
5 changes: 5 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Copyright 2020 Subvisual

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ end
defmodule App.StateMachine do
defstruct [:state, :data]

use Fsmx, transitions: %{
use Fsmx.Struct, transitions: %{
"one" => ["two", "three"],
"two" => ["three", "four"],
"three" => "four"
Expand Down Expand Up @@ -127,7 +127,7 @@ all that business logic into a separate module:
defmodule App.StateMachine do
defstruct [:state]

use Fsmx, fsm: App.Logic
use Fsmx.Struct, fsm: App.Logic
end

defmodule App.BusinessLogic do
Expand Down Expand Up @@ -162,7 +162,7 @@ defmodule App.StateMachineSchema do
field :data, :map
end

use Fsmx, transitions: %{
use Fsmx.Struct, transitions: %{
"one" => ["two", "three"],
"two" => ["three", "four"],
"three" => "four"
Expand Down
9 changes: 8 additions & 1 deletion lib/fsmx.ex
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
defmodule Fsmx do
@moduledoc """
"""

@spec transition(struct(), binary()) :: {:ok, struct} | {:error, any}
def transition(struct, new_state) do
with {:ok, struct} <- before_transition(struct, new_state) do
{:ok, %{struct | state: new_state}}
end
end

if Code.ensure_loaded?(Ecto) do
def transition_changeset(%mod{state: state} = schema, new_state, params \\ %{}) do
@spec transition_changeset(struct(), binary, map) :: {:ok, Ecto.Changeset.t()} | {:error, any}
def(transition_changeset(%mod{state: state} = schema, new_state, params \\ %{})) do
fsm = mod.__fsmx__()

with {:ok, schema} <- before_transition(schema, new_state) do
Expand All @@ -17,6 +22,8 @@ defmodule Fsmx do
end
end

@spec transition_multi(Ecto.Multi.t(), struct(), any, binary, map) ::
{:ok, Ecto.Multi.t()} | {:error, any}
def transition_multi(multi, %mod{state: state} = schema, id, new_state, params \\ %{}) do
fsm = mod.__fsmx__()

Expand Down
35 changes: 33 additions & 2 deletions lib/fsmx/fsm.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
defmodule Fsmx.Fsm do
@moduledoc """
Holds transition and callback logic for finite state machines
By default, when using `use Fsmx.Struct`, this is automatically included as well.
Specifying `use Fsmx.Struct, fsm: MyApp.Fsm` allows you to decouple this, though
```elixir
defmodule MyApp.Struct do
defstruct [:state]
end
defmodule MyApp.Fsm do
use Fsmx.Fsm, transitions: %{}
def before_transition(struct, _from, _to) do
# ...
end
end
"""

@callback before_transition(struct, binary, binary) :: {:ok, struct} | {:error, any}

if Code.ensure_loaded?(Ecto) do
@callback transition_changeset(struct, binary, binary) ::
{:ok, Ecto.Changeset.t()} | {:error, any}
@callback after_transition_multi(struct, binary, binary) :: {:ok, struct} | {:error, any}
end

defmacro __using__(opts \\ []) do
quote do
@before_compile unquote(__MODULE__)
Expand All @@ -13,8 +41,11 @@ defmodule Fsmx.Fsm do
defmacro __before_compile__(_env) do
quote generated: false do
def before_transition(struct, _from, _to), do: {:ok, struct}
def transition_changeset(changeset, _from, _to, _params), do: {:ok, changeset}
def after_transition_multi(struct, _from, _to), do: {:ok, struct}

if Code.ensure_loaded?(Ecto) do
def transition_changeset(changeset, _from, _to, _params), do: {:ok, changeset}
def after_transition_multi(struct, _from, _to), do: {:ok, struct}
end
end
end
end
16 changes: 16 additions & 0 deletions lib/fsmx/struct.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
defmodule Fsmx.Struct do
@moduledoc """
Main module to include finite-state machine logic into your struct/schema
It assumes a `:state` string field exists in your model
Basic usage:
```elixir
defmodule MyApp.Struct do
defstruct [:state]
use Fsmx.Struct, transitions: %{}
end
```
"""

defmacro __using__(opts \\ []) do
quote do
@fsm Keyword.get(unquote(opts), :fsm, __MODULE__)
Expand Down
38 changes: 35 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
defmodule Fsmx.MixProject do
use Mix.Project

@version "0.1.0"

def project do
[
app: :fsmx,
version: "0.1.0",
description: description(),
version: @version,
elixir: "~> 1.8",
applications: applications(Mix.env()),
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
deps: deps()
package: package(),
deps: deps(),
docs: docs()
]
end

Expand All @@ -26,10 +31,37 @@ defmodule Fsmx.MixProject do
[
{:postgrex, ">= 0.0.0", only: :test},
{:ecto, ">= 3.0.0", optional: true},
{:ecto_sql, ">= 3.0.0", optional: true}
{:ecto_sql, ">= 3.0.0", optional: true},
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false},
{:dialyxir, "~> 1.0.0", only: :dev, runtime: false}
]
end

defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]

defp package do
end

defp description do
"A Finite-state machine implementation in Elixir, with opt-in Ecto friendliness."
end

defp package do
[
maintainers: ["Miguel Palhas"],
licenses: ["ISC"],
links: %{"GitHub" => "https://github.com/subvisual/fsmx"},
files: ~w(.formatter.exs mix.exs README.md lib)
]
end

defp docs do
[
extras: ["README.md"],
main: "readme",
source_url: "https://github.com/subvisual/fsmx",
source_ref: "v#{@version}"
]
end
end
7 changes: 7 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"},
"db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"},
"decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"},
"dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
"earmark": {:hex, :earmark, "1.4.5", "62ffd3bd7722fb7a7b1ecd2419ea0b458c356e7168c1f5d65caf09b4fbdd13c8", [:mix], [], "hexpm", "b7d0e6263d83dc27141a523467799a685965bf8b13b6743413f19a7079843f4f"},
"ecto": {:hex, :ecto, "3.4.5", "2bcd262f57b2c888b0bd7f7a28c8a48aa11dc1a2c6a858e45dd8f8426d504265", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8c6d1d4d524559e9b7a062f0498e2c206122552d63eacff0a6567ffe7a8e8691"},
"ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"etso": {:hex, :etso, "0.1.1", "bfc5e30483d397774a64981fc93511d3ed0dcb9d19bc3cba03df7b9555a68636", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "194ed738ce2e1197b326071b42dc092d6df4a7492575a63d6b797a0c59727088"},
"ex_doc": {:hex, :ex_doc, "0.22.1", "9bb6d51508778193a4ea90fa16eac47f8b67934f33f8271d5e1edec2dc0eee4c", [:mix], [{:earmark, "~> 1.4.0", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "d957de1b75cb9f78d3ee17820733dc4460114d8b1e11f7ee4fd6546e69b1db60"},
"makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
"nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
"postgrex": {:hex, :postgrex, "0.15.5", "aec40306a622d459b01bff890fa42f1430dac61593b122754144ad9033a2152f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "ed90c81e1525f65a2ba2279dbcebf030d6d13328daa2f8088b9661eb9143af7f"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
}

0 comments on commit 047ed49

Please sign in to comment.