Cqrs.Command behaviour (cqrs_tools v0.5.28) View Source
The Command
macro allows you to define a command that encapsulates a struct definition,
data validation, dependency validation, and dispatching of the command.
Options
require_all_fields
(:boolean) - Iftrue
, all fields will be required. Defaults totrue
dispatcher
(:atom) - A module that defines adispatch/2
.default_event_values
(:boolean) - Iftrue
, events created usingderive_event/1
orderive_event/2
, will inherit default values from their command fields. Defaults totrue
.
Examples
defmodule CreateUser do
use Cqrs.Command
field :email, :string
field :name, :string
internal_field :id, :binary_id
@impl true
def handle_validate(command, _opts) do
Ecto.Changeset.validate_format(command, :email, ~r/@/)
end
@impl true
def after_validate(%{email: email} = command) do
Map.put(command, :id, UUID.uuid5(:oid, email))
end
@impl true
def handle_dispatch(_command, _opts) do
{:ok, :dispatched}
end
end
Creation
iex> {:error, errors} = CreateUser.new()
...> errors
%{email: ["can't be blank"], name: ["can't be blank"]}
iex> {:ok, %CreateUser{email: email, name: name, id: id}} = CreateUser.new(email: "chris@example.com", name: "chris")
...> %{email: email, name: name, id: id}
%{email: "chris@example.com", id: "052c1984-74c9-522f-858f-f04f1d4cc786", name: "chris"}
iex> %CreateUser{id: "052c1984-74c9-522f-858f-f04f1d4cc786"} = CreateUser.new!(email: "chris@example.com", name: "chris")
Dispatching
iex> {:error, {:invalid_command, errors}} =
...> CreateUser.new(name: "chris", email: "wrong")
...> |> CreateUser.dispatch()
...> errors
%{email: ["has invalid format"]}
iex> CreateUser.new(name: "chris", email: "chris@example.com")
...> |> CreateUser.dispatch()
{:ok, :dispatched}
Event derivation
You can derive events directly from a command.
see derive_event/2
defmodule DeactivateUser do
use Cqrs.Command
field :id, :binary_id
derive_event UserDeactivated
end
Usage with Commanded
defmodule Commanded.Application do
use Commanded.Application,
otp_app: :my_app,
default_dispatch_opts: [
consistency: :strong,
returning: :execution_result
],
event_store: [
adapter: Commanded.EventStore.Adapters.EventStore,
event_store: MyApp.EventStore
]
end
defmodule DeactivateUser do
use Cqrs.Command, dispatcher: Commanded.Application
field :id, :binary_id
derive_event UserDeactivated
end
iex> {:ok, event} = DeactivateUser.new(id: "052c1984-74c9-522f-858f-f04f1d4cc786")
...> |> DeactivateUser.dispatch()
...> %{id: event.id, version: event.version}
%{id: "052c1984-74c9-522f-858f-f04f1d4cc786", version: 1}
Link to this section Summary
Functions
Defines a command field.
The same as field/3
but sets the option internal
to true
.
Describes a supported option for this command.
Callbacks
Called after new
has completed.
Allows one to modify the fully validated command. The changes to the command are validated again after this callback.
This callback is intended to be used as a last chance to do any validation that performs IO.
Allows one to modify the incoming attrs before they are validated. Note that all attribute keys a converted to strings before this callback is invoked.
This callback is intended to authorize the execution of the command.
This callback is intended to be used to run the fully validated command.
Allows one to define any custom data validation aside from casting and requiring fields.
Link to this section Types
Specs
command() :: struct()
Link to this section Functions
Generates an event based on the fields defined in the command.
Accepts all the options that DomainEvent accepts.
Specs
Defines a command field.
:name
- anyatom
:type
- any valid Ecto Schema type:opts
- any valid Ecto Schema field options. Plus::required
-true | false
. Defaults to therequire_all_fields
option.:internal
-true | false
. Iftrue
, this field is meant to be used internally. Iftrue
, the required option will be set tofalse
and the field will be hidden from documentation.:description
- Documentation for the field.
Specs
The same as field/3
but sets the option internal
to true
.
This helps with readability of commands with a large number of fields.
Specs
Describes a supported option for this command.
Options
:default
- this default value if the option is not provided.:description
- The documentation for this option.
Link to this section Callbacks
Specs
Called after new
has completed.
This callback is optional.
Specs
Allows one to modify the fully validated command. The changes to the command are validated again after this callback.
This callback is optional.
Invoked after the handle_validate/2
callback is called.
Specs
This callback is intended to be used as a last chance to do any validation that performs IO.
This callback is optional.
Invoked before handle_dispatch/2
.
Specs
Allows one to modify the incoming attrs before they are validated. Note that all attribute keys a converted to strings before this callback is invoked.
This callback is optional.
Invoked before the handle_validate/2
callback is called.
Specs
This callback is intended to authorize the execution of the command.
This callback is optional.
Invoked after before_dispatch/2
and before handle_dispatch/2
.
Specs
This callback is intended to be used to run the fully validated command.
This callback is required.
Specs
handle_validate( Ecto.Changeset.t(), keyword() ) :: Ecto.Changeset.t()
Allows one to define any custom data validation aside from casting and requiring fields.
This callback is optional.
Invoked when the new()
or new!()
function is called.