Cqrs.Command behaviour (cqrs_tools v0.1.1) 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
- Iftrue
, all fields will be required. Defaults totrue
dispatcher
- A module that defines adispatch/2
.
Examples
defmodule CreateUser do
use Cqrs.Command
field :email, :string
field :name, :string
field :id, :binary_id, required: false
@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> CreateUser.new()
#CreateUser<errors: %{email: ["can't be blank"], name: ["can't be blank"]}>
iex> CreateUser.new(email: "chris@example.com", name: "chris")
#CreateUser<%{email: "chris@example.com", id: "052c1984-74c9-522f-858f-f04f1d4cc786", name: "chris"}>
iex> %{id: "052c1984-74c9-522f-858f-f04f1d4cc786"} = CreateUser.new!(email: "chris@example.com", name: "chris")
Dispatching
iex> {:error, {:invalid_command, state}} =
...> CreateUser.new(name: "chris", email: "wrong")
...> |> CreateUser.dispatch()
...> state.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
Generates a Elixir.Cqrs.DomainEvent
based on the fields defined in the Elixir.Cqrs.Command
.
Defines a command field.
Callbacks
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.
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 a Elixir.Cqrs.DomainEvent
based on the fields defined in the Elixir.Cqrs.Command
.
Accepts all the options that Elixir.Cqrs.DomainEvent
accepts.
Specs
Defines a command field.
:name
- anyatom
:type
- any validEcto.Schema
type:opts
- any validEcto.Schema
field options. Plus::required
-true
|false
. Defaults to therequire_all_fields
option.:description
- Documentation for the field.
Link to this section Callbacks
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
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.