Current section

Files

Jump to
reactor lib reactor dsl where.ex
Raw

lib/reactor/dsl/where.ex

defmodule Reactor.Dsl.Where do
@moduledoc """
A struct used to store the `where` DSL entity.
See `d:Reactor.step.where`.
"""
defstruct __identifier__: nil, description: nil, predicate: nil
alias Reactor.Guard
@type t :: %__MODULE__{
__identifier__: any,
description: nil | String.t(),
predicate:
(Reactor.inputs() -> boolean) | (Reactor.inputs(), Reactor.context() -> boolean)
}
@doc false
def __entity__,
do: %Spark.Dsl.Entity{
name: :where,
describe: """
Only execute the surrounding step if the predicate function returns true.
This is a simple version of `guard` which provides more flexibility at the cost of complexity.
""",
examples: [
"""
step :read_file do
argument :path, input(:path)
run &File.read(&1.path)
where &File.exists?(&1.path)
end
"""
],
args: [:predicate],
target: __MODULE__,
schema: [
predicate: [
type: {:or, [{:mfa_or_fun, 1}, {:mfa_or_fun, 2}]},
required: true,
doc: """
Provide a function which takes the step arguments and optionally the context and returns a boolean value.
"""
],
description: [
type: :string,
required: false,
doc: """
An optional description of the guard.
"""
]
]
}
@doc false
def eval(arguments, context, where) do
if eval_predicate(arguments, context, where) do
:cont
else
{:halt, {:ok, nil}}
end
end
defp eval_predicate(arguments, context, where) when is_function(where.predicate, 2),
do: where.predicate.(arguments, context)
defp eval_predicate(arguments, _context, where) when is_function(where.predicate, 1),
do: where.predicate.(arguments)
defimpl Guard.Build do
@doc false
def build(where) do
{:ok,
[
%Guard{fun: {Reactor.Dsl.Where, :eval, [where]}}
]}
end
end
end