DoubleDown.Repo behaviour (double_down v0.59.0)

Copy Markdown View Source

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:

  • transact is the preferred name for transaction — both are supported. transact is recommended for new code; transaction is provided for compatibility with existing Ecto.Repo call sites so that production code works unchanged through both ContractFacade and DynamicFacade routes.
  • Some rarely-used callbacks omittedcheckout/1, checked_out?/0, put_dynamic_repo/1, get_dynamic_repo/0, to_sql/2 are not included. These can be added incrementally if needed.

Summary

Callbacks

Callbacks

aggregate(queryable, aggregate, field)

@callback aggregate(queryable :: Ecto.Queryable.t(), aggregate :: atom(), field :: atom()) ::
  term()

aggregate(queryable, aggregate, field, opts)

@callback aggregate(
  queryable :: Ecto.Queryable.t(),
  aggregate :: atom(),
  field :: atom(),
  opts :: keyword()
) :: term()

all(queryable)

@callback all(queryable :: Ecto.Queryable.t()) :: [struct()]

all(queryable, opts)

@callback all(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: [struct()]

all_by(queryable, clauses)

@callback all_by(queryable :: Ecto.Queryable.t(), clauses :: keyword() | map()) :: [
  struct()
]

all_by(queryable, clauses, opts)

@callback all_by(
  queryable :: Ecto.Queryable.t(),
  clauses :: keyword() | map(),
  opts :: keyword()
) :: [
  struct()
]

delete(struct_or_changeset)

@callback delete(struct_or_changeset :: struct() | Ecto.Changeset.t()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

delete(struct_or_changeset, opts)

@callback delete(struct_or_changeset :: struct() | Ecto.Changeset.t(), opts :: keyword()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

delete!(struct_or_changeset)

@callback delete!(struct_or_changeset :: struct() | Ecto.Changeset.t()) :: struct()

delete!(struct_or_changeset, opts)

@callback delete!(struct_or_changeset :: struct() | Ecto.Changeset.t(), opts :: keyword()) ::
  struct()

delete_all(queryable, opts)

@callback delete_all(queryable :: Ecto.Queryable.t(), opts :: keyword()) ::
  {non_neg_integer(), nil | list()}

exists?(queryable)

@callback exists?(queryable :: Ecto.Queryable.t()) :: boolean()

exists?(queryable, opts)

@callback exists?(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: boolean()

get(queryable, id)

@callback get(queryable :: Ecto.Queryable.t(), id :: term()) :: struct() | nil

get(queryable, id, opts)

@callback get(queryable :: Ecto.Queryable.t(), id :: term(), opts :: keyword()) ::
  struct() | nil

get!(queryable, id)

@callback get!(queryable :: Ecto.Queryable.t(), id :: term()) :: struct()

get!(queryable, id, opts)

@callback get!(queryable :: Ecto.Queryable.t(), id :: term(), opts :: keyword()) ::
  struct()

get_by(queryable, clauses)

@callback get_by(queryable :: Ecto.Queryable.t(), clauses :: keyword() | map()) ::
  struct() | nil

get_by(queryable, clauses, opts)

@callback get_by(
  queryable :: Ecto.Queryable.t(),
  clauses :: keyword() | map(),
  opts :: keyword()
) ::
  struct() | nil

get_by!(queryable, clauses)

@callback get_by!(queryable :: Ecto.Queryable.t(), clauses :: keyword() | map()) ::
  struct()

get_by!(queryable, clauses, opts)

@callback get_by!(
  queryable :: Ecto.Queryable.t(),
  clauses :: keyword() | map(),
  opts :: keyword()
) ::
  struct()

in_transaction?()

@callback in_transaction?() :: boolean()

insert(struct_or_changeset)

@callback insert(struct_or_changeset :: Ecto.Changeset.t() | struct()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

insert(struct_or_changeset, opts)

@callback insert(struct_or_changeset :: Ecto.Changeset.t() | struct(), opts :: keyword()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

insert!(struct_or_changeset)

@callback insert!(struct_or_changeset :: Ecto.Changeset.t() | struct()) :: struct()

insert!(struct_or_changeset, opts)

@callback insert!(struct_or_changeset :: Ecto.Changeset.t() | struct(), opts :: keyword()) ::
  struct()

insert_all(source, entries, opts)

@callback insert_all(
  source :: Ecto.Queryable.t() | binary(),
  entries :: [map() | keyword()],
  opts :: keyword()
) :: {non_neg_integer(), nil | list()}

insert_or_update(changeset)

@callback insert_or_update(changeset :: Ecto.Changeset.t()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

insert_or_update(changeset, opts)

@callback insert_or_update(changeset :: Ecto.Changeset.t(), opts :: keyword()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

insert_or_update!(changeset)

@callback insert_or_update!(changeset :: Ecto.Changeset.t()) :: struct()

insert_or_update!(changeset, opts)

@callback insert_or_update!(changeset :: Ecto.Changeset.t(), opts :: keyword()) ::
  struct()

load(schema_or_map, data)

@callback load(
  schema_or_map :: module() | map(),
  data :: map() | keyword() | {list(), list()}
) ::
  struct() | map()

one(queryable)

@callback one(queryable :: Ecto.Queryable.t()) :: struct() | nil

one(queryable, opts)

@callback one(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: struct() | nil

one!(queryable)

@callback one!(queryable :: Ecto.Queryable.t()) :: struct()

one!(queryable, opts)

@callback one!(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: struct()

preload(structs_or_struct_or_nil, preloads)

@callback preload(
  structs_or_struct_or_nil :: [struct()] | struct() | nil,
  preloads :: term()
) ::
  [struct()] | struct() | nil

preload(structs_or_struct_or_nil, preloads, opts)

@callback preload(
  structs_or_struct_or_nil :: [struct()] | struct() | nil,
  preloads :: term(),
  opts :: keyword()
) :: [struct()] | struct() | nil

query(sql)

@callback query(sql :: String.t()) :: {:ok, term()} | {:error, term()}

query(sql, params)

@callback query(sql :: String.t(), params :: list()) :: {:ok, term()} | {:error, term()}

query(sql, params, opts)

@callback query(sql :: String.t(), params :: list(), opts :: keyword()) ::
  {:ok, term()} | {:error, term()}

query!(sql)

@callback query!(sql :: String.t()) :: term()

query!(sql, params)

@callback query!(sql :: String.t(), params :: list()) :: term()

query!(sql, params, opts)

@callback query!(sql :: String.t(), params :: list(), opts :: keyword()) :: term()

reload(struct_or_structs)

@callback reload(struct_or_structs :: struct() | [struct()]) ::
  struct() | nil | [struct() | nil]

reload(struct_or_structs, opts)

@callback reload(struct_or_structs :: struct() | [struct()], opts :: keyword()) ::
  struct() | nil | [struct() | nil]

reload!(struct_or_structs)

@callback reload!(struct_or_structs :: struct() | [struct()]) :: struct() | [struct()]

reload!(struct_or_structs, opts)

@callback reload!(struct_or_structs :: struct() | [struct()], opts :: keyword()) ::
  struct() | [struct()]

rollback(value)

@callback rollback(value :: term()) :: no_return()

stream(queryable)

@callback stream(queryable :: Ecto.Queryable.t()) :: Enum.t()

stream(queryable, opts)

@callback stream(queryable :: Ecto.Queryable.t(), opts :: keyword()) :: Enum.t()

transact(fun_or_multi, opts)

@callback transact(fun_or_multi :: term(), opts :: keyword()) ::
  {:ok, term()} | {:error, term()} | {:error, term(), term(), term()}

transaction(fun_or_multi, opts)

@callback transaction(fun_or_multi :: term(), opts :: keyword()) ::
  {:ok, term()} | {:error, term()} | {:error, term(), term(), term()}

update(changeset)

@callback update(changeset :: Ecto.Changeset.t()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

update(changeset, opts)

@callback update(changeset :: Ecto.Changeset.t(), opts :: keyword()) ::
  {:ok, struct()} | {:error, Ecto.Changeset.t()}

update!(changeset)

@callback update!(changeset :: Ecto.Changeset.t()) :: struct()

update!(changeset, opts)

@callback update!(changeset :: Ecto.Changeset.t(), opts :: keyword()) :: struct()

update_all(queryable, updates, opts)

@callback update_all(
  queryable :: Ecto.Queryable.t(),
  updates :: keyword(),
  opts :: keyword()
) ::
  {non_neg_integer(), nil | list()}