Packages

DDD semantics for blunt

Current section

Files

Jump to
blunt_ddd lib blunt entity identity.ex
Raw

lib/blunt/entity/identity.ex

defmodule Blunt.Entity.Identity do
@moduledoc false
@default {:id, Ecto.UUID, autogenerate: false}
alias Blunt.Message.Metadata
alias Blunt.{Behaviour, Entity.Error, Entity.Identity}
def pop(opts) do
opts
|> Keyword.update(:identity, @default, &ensure_field/1)
|> Keyword.pop!(:identity)
end
defp ensure_field({name, type}), do: {name, type, []}
defp ensure_field({name, type, config}), do: {name, type, config}
defp ensure_field(value) when value in [false, nil] do
raise Error, message: "Entities require a primary key"
end
defp ensure_field(_other) do
raise Error, message: "identity must be either {name, type} or {name, type, options}"
end
defmacro generate do
quote do
def identity(%__MODULE__{} = entity),
do: Identity.identity(__MODULE__, entity)
def equals?(left, right),
do: Identity.equals?(__MODULE__, left, right)
end
end
def identity(entity_module, entity) do
Behaviour.validate!(entity_module, Blunt.Entity)
{field_name, _type, _config} = Metadata.primary_key(entity_module)
Map.fetch!(entity, field_name)
end
def equals?(entity_module, %{__struct__: entity_module} = left, %{__struct__: entity_module} = right) do
identity(entity_module, left) == identity(entity_module, right)
end
def equals?(entity_module, _left, _right) do
raise Error, message: "#{inspect(entity_module)}.equals? requires two #{inspect(entity_module)} structs"
end
end