Packages
cqrs_tools
0.5.21
0.5.28
0.5.27
0.5.26
0.5.25
0.5.24
0.5.23
0.5.22
0.5.21
0.5.20
0.5.19
0.5.18
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.22
0.3.21
0.3.20
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.30
0.2.29
0.2.28
0.2.27
0.2.26
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.1
0.1.0
A collection of handy Elixir macros for CQRS applications.
Current section
Files
Jump to
Current section
Files
lib/cqrs/domain_event.ex
defmodule Cqrs.DomainEvent do
@moduledoc """
Defines a new domain event struct
## Options
* `:from` _optional_ - a struct to derive fields from.
* `:with` _optional_ - a list of `atom` field names to add.
* `:drop` _optional_ - a list of `atom` field names to remove from any field derived from the struct in the `:from` option.
* `:version` _optional_ - a version value. Defaults to `1`
## Example
defmodule DeleteUser do
use Cqrs.Command
field :id, :integer
def handle_dispatch(command, _opts) do
{:ok, :no_impl}
end
end
defmodule UserDeleted do
use Cqrs.DomainEvent,
from: DeleteUser,
with: [:from],
version: 2
end
iex> cmd = DeleteUser.new!(id: 668)
...> event = UserDeleted.new(cmd, from: "chris")
...> %{id: event.id, from: event.from, version: event.version}
%{id: 668, from: "chris", version: 2}
"""
alias Cqrs.{DomainEvent, Guards}
defmacro __using__(opts) do
create_jason_encoders = Application.get_env(:cqrs_tools, :create_jason_encoders, true)
quote generated: true, location: :keep do
version = Keyword.get(unquote(opts), :version, 1)
explicit_keys = DomainEvent.explicit_keys(unquote(opts))
inherited_keys = DomainEvent.inherit_keys(unquote(opts))
keys =
Keyword.merge(inherited_keys, explicit_keys, fn
_key, nil, nil -> nil
_key, nil, value -> value
_key, value, nil -> value
end)
if unquote(create_jason_encoders) and Code.ensure_loaded?(Jason), do: @derive(Jason.Encoder)
defstruct keys
|> DomainEvent.drop_keys(unquote(opts))
|> Kernel.++([{:created_at, nil}, {:version, version}])
def new(source \\ [], attrs \\ []) do
DomainEvent.new(__MODULE__, source, attrs)
end
end
end
@doc false
def drop_keys(keys, opts) do
keys_to_drop = Keyword.get(opts, :drop, []) |> List.wrap()
Enum.reject(keys, fn
{:__struct__, _} -> true
{:created_at, _} -> true
{name, _default_value} -> Enum.member?(keys_to_drop, name)
name -> Enum.member?(keys_to_drop, name)
end)
end
@doc false
def inherit_keys(opts) do
case Keyword.get(opts, :from) do
nil ->
[]
source when is_atom(source) ->
Guards.ensure_is_struct!(source)
source
|> struct()
|> Map.to_list()
source ->
"#{source} should be a valid struct to use with DomainEvent"
end
end
@doc false
def explicit_keys(opts) do
opts
|> Keyword.get(:with, [])
|> List.wrap()
|> Enum.map(fn
field when is_tuple(field) -> field
field when is_atom(field) or is_binary(field) -> {field, nil}
end)
end
@doc false
def new(module, source, attrs) when is_atom(module) do
fields =
source
|> normalize()
|> Map.merge(normalize(attrs))
|> Map.put(:created_at, Cqrs.Clock.utc_now(module))
struct(module, fields)
end
defp normalize(values) when is_struct(values), do: Map.from_struct(values)
defp normalize(values) when is_map(values), do: values
defp normalize(values) when is_list(values), do: Enum.into(values, %{})
end