EctoHooks.Delta (ecto_hooks v2.0.0)

View Source

Metadata struct passed to after_* hooks containing information about the operation.

The Delta struct provides context about which repository operation triggered the hook, allowing for conditional logic and introspection within your hooks.

Fields

  • :repo_callback - The c:Ecto.Repo function that was called (e.g., :insert for c:Ecto.Repo.insert/2, :get for c:Ecto.Repo.get/3)
  • :hook - The hook currently executing (e.g., :after_insert, :after_get)
  • :source - The original input to the repo operation (changeset, queryable, or struct)
  • :queryable - Set if source is an t:Ecto.Queryable.t/0 (query or schema module)
  • :changeset - Set if source is an t:Ecto.Changeset.t/0
  • :record - Set if source is a schema struct or list

Examples

Conditional Hook Logic

def after_get(user, %Delta{repo_callback: :get}) do
  # Only log when fetching single users via c:Ecto.Repo.get/3
  # (not during c:Ecto.Repo.all/2)
  Logger.info("Fetched user: #{user.id}")
  user
end

def after_get(user, %Delta{repo_callback: :all}) do
  # Skip logging for bulk fetches via c:Ecto.Repo.all/2
  user
end

Inspecting Changes

def after_update(user, %Delta{changeset: changeset}) do
  if Ecto.Changeset.changed?(changeset, :email) do
    EmailVerification.send_confirmation(user)
  end
  user
end

Delegating to Private Functions

def after_insert(user, delta), do: handle_after_hook(user, delta)
def after_update(user, delta), do: handle_after_hook(user, delta)

defp handle_after_hook(user, %Delta{hook: :after_insert}) do
  # Logic specific to inserts
  send_welcome_email(user)
  user
end

defp handle_after_hook(user, %Delta{hook: :after_update}) do
  # Logic specific to updates
  invalidate_cache(user)
  user
end

Type

The Delta struct is defined as:

@type t :: %__MODULE__{
  repo_callback: repo_callback(),
  hook: hook(),
  source: term(),
  queryable: Ecto.Queryable.t() | nil,
  changeset: Ecto.Changeset.t() | nil,
  record: struct() | [struct()] | nil
}

Where repo_callback() is one of:

  • :all (c:Ecto.Repo.all/2)
  • :delete (c:Ecto.Repo.delete/2)
  • :delete! (c:Ecto.Repo.delete!/2)
  • :get (c:Ecto.Repo.get/3)
  • :get! (c:Ecto.Repo.get!/3)
  • :get_by (c:Ecto.Repo.get_by/3)
  • :get_by! (c:Ecto.Repo.get_by!/3)
  • :insert (c:Ecto.Repo.insert/2)
  • :insert! (c:Ecto.Repo.insert!/2)
  • :insert_or_update (c:Ecto.Repo.insert_or_update/2)
  • :insert_or_update! (c:Ecto.Repo.insert_or_update!/2)
  • :one (c:Ecto.Repo.one/2)
  • :one! (c:Ecto.Repo.one!/2)
  • :preload (c:Ecto.Repo.preload/3)
  • :reload (c:Ecto.Repo.reload/2)
  • :reload! (c:Ecto.Repo.reload!/2)
  • :update (c:Ecto.Repo.update/2)
  • :update! (c:Ecto.Repo.update!/2)

And hook() is one of: :after_delete, :after_get, :after_insert, :after_update, :before_delete, :before_insert, :before_update

Summary

Types

hook()

@type hook() ::
  :before_update
  | :before_insert
  | :before_delete
  | :after_update
  | :after_insert
  | :after_get
  | :after_delete

repo_callback()

@type repo_callback() ::
  :update
  | :update!
  | :preload
  | :reload
  | :reload!
  | :one
  | :one!
  | :insert_or_update
  | :insert_or_update!
  | :insert
  | :insert!
  | :get_by
  | :get_by!
  | :get
  | :get!
  | :delete
  | :delete!
  | :all

t()

@type t() :: %EctoHooks.Delta{
  changeset: term(),
  hook: term(),
  queryable: term(),
  record: term(),
  repo_callback: term(),
  source: term()
}

Functions

new!(repo_callback, hook, source)

@spec new!(repo_callback(), hook(), source :: any()) :: t() | no_return()