Exop v1.1.4 Exop.Operation behaviour View Source
Provides macros for an operation’s contract definition and process/1 function.
Example
defmodule SomeOperation do
use Exop.Operation
parameter :param1, type: :integer, required: true
parameter :param2, type: :string, length: %{max: 3}, format: ~r/foo/
def process(params) do
"This is the operation's result with one of the params = " <> params[:param1]
end
end
Link to this section Summary
Functions
Authorizes an action with predefined policy (see policy
macro docs).
If authorization fails, any code after (below) auth check will be postponed (an error {:error, {:auth, _reason}}
will be returned immediately)
Returns policy that was defined in an operation
Defines a fallback module that will be used for an operation’s non-ok-tuple (fail) result handling.
defmodule MultiplyByTenOperation do
use Exop.Operation
Defines a parameter with name
and opts
in an operation contract.
Options could include the parameter value checks and transformations (like coercion)
Defines a policy that will be used for authorizing the possibility of a user to invoke an operation.
defmodule ReadOperation do
use Exop.Operation
Callbacks
Operation’s entry point. Takes defined contract as the single parameter.
Contract itself is a Keyword.t
list: [param_name: param_value]
Link to this section Functions
Authorizes an action with predefined policy (see policy
macro docs).
If authorization fails, any code after (below) auth check will be postponed (an error {:error, {:auth, _reason}}
will be returned immediately)
Returns policy that was defined in an operation.
Defines a fallback module that will be used for an operation’s non-ok-tuple (fail) result handling.
defmodule MultiplyByTenOperation do
use Exop.Operation
fallback LoggerFallback
parameter :a, type: :integer, required: true
def process(%{a: a}), do: a * 10
end
A fallback module itself might be:
defmodule LoggerFallback do
use Exop.Fallback
require Logger
def process(operation_module, params_passed_to_the_operation, operation_error_result) do
Logger.error("Oops")
end
end
If return: true
option is provided then failed operation’s run/1
will return the
fallback’s process/3
result.
Defines a parameter with name
and opts
in an operation contract.
Options could include the parameter value checks and transformations (like coercion).
Example
parameter :some_param, type: :map, required: true
Available checks are:
type
Checks whether a parameter’s value is of declared type.
parameter :some_param, type: :map
required
Checks the presence of a parameter in passed params collection.
parameter :some_param, required: true
default
Checks if the parameter is missed and assigns default value to it if so.
parameter :some_param, default: "default value"
numericality
Checks whether a parameter’s value is a number and passes constraints (if constraints were defined).
parameter :some_param, numericality: %{equal_to: 10, greater_than: 0,
greater_than_or_equal_to: 10,
less_than: 20,
less_than_or_equal_to: 10}
in
Checks whether a parameter’s value is within a given list.
parameter :some_param, in: ~w(a b c)
not_in
Checks whether a parameter’s value is not within a given list.
parameter :some_param, not_in: ~w(a b c)
format
Checks wether parameter’s value matches given regex.
parameter :some_param, format: ~r/foo/
length
Checks the length of a parameter’s value.
parameter :some_param, length: %{min: 5, max: 10, is: 7, in: 5..8}
inner
Checks the inner of either Map or Keyword parameter.
parameter :some_param, type: :map, inner: %{
a: [type: :integer, required: true],
b: [type: :string, length: %{min: 1, max: 6}]
}
struct
Checks whether the given parameter is expected structure.
parameter :some_param, struct: %SomeStruct{}
list_item
Checks whether each of list items conforms defined checks. An item’s checks could be any that Exop offers:
parameter :list_param, list_item: %{type: :string, length: %{min: 7}}
func
Checks whether an item is valid over custom validation function.
parameter :some_param, func: &__MODULE__.your_validation/2
def your_validation(_params, param), do: !is_nil(param)
Coercion
It is possible to coerce a parameter before the contract validation, all validation checks
will be invoked on coerced parameter value.
Since coercion changes a parameter before any validation has been invoked,
default values are resolved (with :default
option) before the coercion.
The flow looks like: Resolve param default value -> Coerce -> Validate coerced
parameter :some_param, default: 1, numericality: %{greater_than: 0}, coerce_with: &__MODULE__.coerce/1
def coerce(x), do: x * 2
For more information and examples check out general Exop docs.
Defines a policy that will be used for authorizing the possibility of a user to invoke an operation.
defmodule ReadOperation do
use Exop.Operation
policy MonthlyReportPolicy, :can_read?
parameter :user, required: true, struct: %User{}
def process(params) do
authorize(params.user)
# make some reading...
end
end
A policy itself might be:
defmodule MonthlyReportPolicy do
# not only Keyword or Map as an argument since 1.1.1
def can_read?(%User{role: "manager"}), do: true
def can_read?(_opts), do: false
def can_write?(%User{role: "manager"}), do: true
def can_write?(_opts), do: false
end
Link to this section Callbacks
process(map()) :: {:ok, any()} | Exop.Validation.validation_error() | {:interrupt, any()} | :ok | no_return()
Operation’s entry point. Takes defined contract as the single parameter.
Contract itself is a Keyword.t
list: [param_name: param_value]