An extensible protocol for processing commands.
Pro Tip
When defining implementations, use data structures and code which will raise errors when something is missing or invalid.
This way, the Elixir 1.20+ compiler can perform compile-time checks on the options and raise errors during development.
Caution
Fallback implementations for Must are dangerous and intended only for prototyping or testing. Be careful to avoid shipping fallback implementations in production.
One exception is Must.Command.be_valid!/2, which may be redundant when commands are defined as Ecto schemas with changesets. See the function docs for more information.
Summary
Functions
Determine whether an actor is permitted to execute a command.
Translate the command to an event struct.
Determine whether the given params produce a valid command.
Types
@type t() :: term()
All the types that implement this protocol.
Functions
Determine whether an actor is permitted to execute a command.
If permitted, return the command, otherwise raise an error.
Translate the command to an event struct.
Returns a list of events resulting from a single command.
Determine whether the given params produce a valid command.
If valid, return the command, otherwise raise an error.
Fallback Implemenation
When commands are defined as Ecto schemas with changesets, it may be safe to define a fallback implementation to reduce repetetive code.
The following implementation will be used when no specific implementation is defined for the command. In this example, opts must be a keyword list with :params key.
# This code may live in lib/my_app.ex or any appropriate file.
defimpl Must.Command, for: Any do
def be_valid!(command, opts) do
params = Keyword.fetch!(opts, :params)
module = command.__struct__
command
|> module.changeset(params)
|> Ecto.Changeset.apply_action!(:validate)
end
end