Organize
module
Kit::Organizer::Services::Organize
View Source
Organizer passes the result of a callable to another callable (as long as the result is successfull).
It is mostly useful when you need to execute a series of operations resembling a pipeline.
You might alredy be familiar with some solutions that deal with this (Promises, Railway Programming, Pipe operators).
Kit::Organizer
is a flavor of functional interactor.
Introduction
Describing a list of operations often leads to code that is difficult to follow or nested requires a lot of nesting. For instance:
fire_user_created_event(persist_user(validate_password(validate_email({ email: email, password: password }))))
# or
valid_email? = validate_email(email)
valid_password? = validate_password(password)
if valid_email? && valid_password?
user = persist_user(email: email, password: password)
if user
fire_user_created_event(user: user)
end
end
With Organizer
, this is expressed as:
Kit::Organize::Services::Organize.call(
list: [
[:alias, :validate_email],
[:alias, :validate_password],
[:alias, :persist_user],
[:alias, :fire_user_created_event],
],
ctx: {
email: '',
password: '',
},
)
Context
An organizer uses a context. The context contains everything the set of operations need to work. When an operation is called, it can affect the context.
Callable
A callable is expected to return a result tupple of the following format:
[:ok] || [:ok, context_update] || [:error] || [:error, context_update]
Link to this section Summary ⚠️ Private APIs are currently hidden.
Link to this section Class methods 3 ⚠️ Private APIs are currently hidden.
Display debug information when ENV['LOG_ORGANIZER']
is set
Run a list
of operations
(callable) in order. Each results update the initial ctx
which is then sent to the next operation.
An operation
needs to be a callable, but it can be resolved from other format (see #to_callable)
Note: Every operation is expected to return a tupple of the format [:ok]
or [:error]
with an optional context update ([:ok, { new_ctx_key: 'value' }]
, [:errors, { errors: [{ detail: 'Error explaination' }], }]
). If an :error
tupple is returned, the next operations are canceled and call
will return.
contract Ct::Hash[list: Ct::Operations, ctx: Ct::Optional[Ct::Hash], filter: Ct::Optional[Ct::Or[Ct::Hash[ok: Ct::Array], Ct::Hash[error: Ct::Array]]]] => Ct::ResultTupple
Sanitizes returned errors, if any. contract Ct::Hash[result: Ct::ResultTupple] => Ct::ResultTupple