Current section
Files
Jump to
Current section
Files
lib/ecto_as_state_machine.ex
defmodule EctoAsStateMachine do
defmodule Helpers do
defmacro easm(opts) do
app = Mix.Project.config[:app]
default_repo = Application.get_env(app, :ecto_repos, []) |> List.first
repo = Keyword.get(opts, :repo, default_repo)
valid_states = Keyword.get(opts, :states)
column = Keyword.get(opts, :column, :state)
initial = Keyword.get(opts, :initial)
events = Keyword.get(opts, :events)
|> Enum.map(fn(event) ->
Keyword.put_new(event, :callback, quote(do: fn(model) -> model end))
end)
|> Enum.map(fn(event) ->
Keyword.update!(event, :callback, &Macro.escape/1)
end)
function_prefix = if column == :state, do: nil, else: "#{column}_"
quote bind_quoted: [
valid_states: valid_states,
events: events,
column: column,
repo: repo,
initial: initial,
function_prefix: function_prefix
] do
def unquote(:"#{function_prefix}states")() do
unquote(valid_states)
end
def unquote(:"#{function_prefix}events")() do
unquote(events) |> Enum.map(fn(x) -> x[:name] end)
end
events
|> Enum.each(fn(event) ->
unless event[:to] in valid_states do
raise "Target state :#{event[:to]} is not present in states"
end
def unquote(event[:name])(model) do
EctoAsStateMachine.State.update(%{
event: unquote(event),
model: model,
column: unquote(column),
states: unquote(valid_states),
initial: unquote(initial)
})
end
def unquote(:"#{event[:name]}!")(model) do
EctoAsStateMachine.State.update!(%{
repo: unquote(repo),
event: unquote(event),
model: model,
column: unquote(column),
states: unquote(valid_states),
initial: unquote(initial)
})
end
def unquote(:"can_#{event[:name]}?")(model) do
EctoAsStateMachine.State.can_event?(%{
event: unquote(event),
model: model,
column: unquote(column),
states: unquote(valid_states),
initial: unquote(initial)
})
end
end)
valid_states
|> Enum.each(fn(state) ->
def unquote(:"#{state}?")(model) do
EctoAsStateMachine.State.is_state?(%{
model: model,
column: unquote(column),
state: unquote(state),
states: unquote(valid_states),
initial: unquote(initial)
})
end
end)
def unquote(column)(model) do
"#{EctoAsStateMachine.State.state_with_initial(Map.get(model, unquote(column)), %{states: unquote(valid_states), initial: unquote(initial)})}"
end
end
end
end
@doc false
defmacro __using__(_) do
quote do
import EctoAsStateMachine.Helpers
end
end
end