Packages
Adds callbacks/hooks to Ecto: `after_insert`, `after_update`, `after_delete`, `after_get`, `before_insert`, `before_update`, `before_delete`. Useful for setting virtual fields and centralising logic.
Current section
Files
Jump to
Current section
Files
lib/ecto_hooks/middleware/after.ex
defmodule EctoHooks.Middleware.After do
@moduledoc "Module containing implementation for all `after_` hooks"
@behaviour EctoMiddleware
@impl EctoMiddleware
def middleware(resource, resolution) when resolution.action in [:insert, :insert!] do
EctoHooks.after_insert(resource, resolution.action, resolution.before_output)
end
def middleware(resource, resolution) when resolution.action in [:update, :update!] do
EctoHooks.after_update(resource, resolution.action, resolution.before_output)
end
def middleware(resource, resolution) when resolution.action in [:delete, :delete!] do
EctoHooks.after_delete(resource, resolution.action, resolution.before_output)
end
def middleware(resource, resolution)
when resolution.action in [:insert_or_update, :insert_or_update!] and
resolution.entity.data.__meta__.state == :loaded do
EctoHooks.after_update(resource, resolution.action, resolution.before_output)
end
def middleware(resource, resolution)
when resolution.action in [:insert_or_update, :insert_or_update!] and
resolution.entity.data.__meta__.state == :built do
EctoHooks.after_insert(resource, resolution.action, resolution.before_output)
end
def middleware(resource, resolution) when resolution.action in [:preload, :preload!] do
case Enum.at(resolution.args, 1) do
preloads when is_list(preloads) ->
handle_preloads(resource, preloads)
preload when is_atom(preload) ->
handle_preloads(resource, [preload])
_otherwise ->
resource
end
end
def middleware(resource, resolution)
when resolution.action in [
:get,
:get!,
:get_by,
:get_by!,
:one,
:one!,
:reload,
:reload!,
:all,
:reload,
:reload!
] do
EctoHooks.after_get(resource, resolution.action, resolution.before_output)
end
def middleware(resource, _resolution) do
resource
end
defp handle_preloads(structs, preloads) when is_list(structs) do
Enum.map(structs, fn struct -> handle_preloads(struct, preloads) end)
end
defp handle_preloads(struct, preloads) do
struct
|> traverse_preloads(preloads)
|> EctoHooks.after_get(:preload, struct)
end
defp traverse_preloads(nil, _preloads), do: nil
defp traverse_preloads(struct, preloads) when is_list(preloads) do
Enum.reduce(preloads, struct, fn preload, acc -> traverse_preloads(acc, preload) end)
end
defp traverse_preloads(struct, {preload, nested_preloads}) do
{_, updated_struct} =
Map.get_and_update(struct, preload, fn v ->
{v, handle_preloads(v, nested_preloads)}
end)
updated_struct
end
defp traverse_preloads(struct, preload) when is_atom(preload) do
{_, updated_struct} =
Map.get_and_update(struct, preload, fn v ->
{v, handle_preloads(v, [])}
end)
updated_struct
end
defp traverse_preloads(queryable, _preload) do
queryable
end
end