Repo contract for common Ecto Repo operations.
Provides defcallback declarations for the standard write and read operations
from Ecto.Repo, so that code using DoubleDown for database access doesn't
need to redeclare these with identical boilerplate.
Usage
# Define a facade in your app:
defmodule MyApp.Repo do
use DoubleDown.ContractFacade, contract: DoubleDown.Repo, otp_app: :my_app
end
changeset = User.changeset(%User{}, attrs)
{:ok, user} = MyApp.Repo.insert(changeset)
user = MyApp.Repo.get!(User, user_id)Write Operations
Write operations return {:ok, struct()} | {:error, Ecto.Changeset.t()}.
Bulk Operations
update_all/3 and delete_all/2 follow Ecto's return convention of
{count, nil | list}.
Read Operations
Read operations follow Ecto's conventions: get/2, get_by/2, one/1
return nil on not-found; all/1 returns a list; exists?/1 returns
a boolean; aggregate/3 returns a term.
Raise-on-not-found variants (get!/2, get_by!/2, one!/1) mirror
Ecto's semantics.
Relationship to Ecto.Repo
This module is a DoubleDown.Contract, not an Ecto.Repo behaviour
implementation. It mirrors most of the Ecto.Repo API but differs in
two ways:
transactis the preferred name fortransaction— both are supported.transactis recommended for new code;transactionis provided for compatibility with existingEcto.Repocall sites so that production code works unchanged through both ContractFacade and DynamicFacade routes.- Some rarely-used callbacks omitted —
checkout/1,checked_out?/0,put_dynamic_repo/1,get_dynamic_repo/0,to_sql/2are not included. These can be added incrementally if needed.
Summary
Callbacks
@callback aggregate(queryable :: Ecto.Queryable.t(), aggregate :: atom(), field :: atom()) :: term()
@callback aggregate( queryable :: Ecto.Queryable.t(), aggregate :: atom(), field :: atom(), opts :: keyword() ) :: term()
@callback all(queryable :: Ecto.Queryable.t()) :: [struct()]
@callback all(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: [struct()]
@callback all_by(queryable :: Ecto.Queryable.t(), clauses :: keyword() | map()) :: [ struct() ]
@callback all_by( queryable :: Ecto.Queryable.t(), clauses :: keyword() | map(), opts :: keyword() ) :: [ struct() ]
@callback delete(struct_or_changeset :: struct() | Ecto.Changeset.t()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback delete(struct_or_changeset :: struct() | Ecto.Changeset.t(), opts :: keyword()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback delete!(struct_or_changeset :: struct() | Ecto.Changeset.t()) :: struct()
@callback delete!(struct_or_changeset :: struct() | Ecto.Changeset.t(), opts :: keyword()) :: struct()
@callback delete_all(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: {non_neg_integer(), nil | list()}
@callback exists?(queryable :: Ecto.Queryable.t()) :: boolean()
@callback exists?(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: boolean()
@callback get(queryable :: Ecto.Queryable.t(), id :: term()) :: struct() | nil
@callback get(queryable :: Ecto.Queryable.t(), id :: term(), opts :: keyword()) :: struct() | nil
@callback get!(queryable :: Ecto.Queryable.t(), id :: term()) :: struct()
@callback get!(queryable :: Ecto.Queryable.t(), id :: term(), opts :: keyword()) :: struct()
@callback get_by(queryable :: Ecto.Queryable.t(), clauses :: keyword() | map()) :: struct() | nil
@callback get_by( queryable :: Ecto.Queryable.t(), clauses :: keyword() | map(), opts :: keyword() ) :: struct() | nil
@callback get_by!(queryable :: Ecto.Queryable.t(), clauses :: keyword() | map()) :: struct()
@callback get_by!( queryable :: Ecto.Queryable.t(), clauses :: keyword() | map(), opts :: keyword() ) :: struct()
@callback in_transaction?() :: boolean()
@callback insert(struct_or_changeset :: Ecto.Changeset.t() | struct()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback insert(struct_or_changeset :: Ecto.Changeset.t() | struct(), opts :: keyword()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback insert!(struct_or_changeset :: Ecto.Changeset.t() | struct()) :: struct()
@callback insert!(struct_or_changeset :: Ecto.Changeset.t() | struct(), opts :: keyword()) :: struct()
@callback insert_all( source :: Ecto.Queryable.t() | binary(), entries :: [map() | keyword()], opts :: keyword() ) :: {non_neg_integer(), nil | list()}
@callback insert_or_update(changeset :: Ecto.Changeset.t()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback insert_or_update(changeset :: Ecto.Changeset.t(), opts :: keyword()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback insert_or_update!(changeset :: Ecto.Changeset.t()) :: struct()
@callback insert_or_update!(changeset :: Ecto.Changeset.t(), opts :: keyword()) :: struct()
@callback one(queryable :: Ecto.Queryable.t()) :: struct() | nil
@callback one(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: struct() | nil
@callback one!(queryable :: Ecto.Queryable.t()) :: struct()
@callback one!(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: struct()
@callback stream(queryable :: Ecto.Queryable.t()) :: Enum.t()
@callback stream(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: Enum.t()
@callback update(changeset :: Ecto.Changeset.t()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback update(changeset :: Ecto.Changeset.t(), opts :: keyword()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}
@callback update!(changeset :: Ecto.Changeset.t()) :: struct()
@callback update!(changeset :: Ecto.Changeset.t(), opts :: keyword()) :: struct()
@callback update_all( queryable :: Ecto.Queryable.t(), updates :: keyword(), opts :: keyword() ) :: {non_neg_integer(), nil | list()}