Skip to content

Instantly share code, notes, and snippets.

@woylie
Last active May 19, 2025 06:44
Show Gist options
  • Select an option

  • Save woylie/63e4a010fb5e047352ca52126b605cd9 to your computer and use it in GitHub Desktop.

Select an option

Save woylie/63e4a010fb5e047352ca52126b605cd9 to your computer and use it in GitHub Desktop.
Repo.fetch
defmodule MyApp.Repo do
use Ecto.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.Postgres
alias Ecto.Queryable
alias Ecto.Schema
@doc """
Fetches a single struct from the data store where the primary key matches the
given key. Returns an ok/error tuple.
`Ecto.Query.CastError` is rescued and an error tuple is returned instead in
order to handle malformed binary IDs.
"""
@spec fetch(Queryable.t(), term, keyword) ::
{:ok, Schema.t()} | {:error, :not_found}
def fetch(queryable, id, opts \\ []) do
case get(queryable, id, opts) do
nil -> {:error, :not_found}
something -> {:ok, something}
end
rescue
Ecto.Query.CastError -> {:error, :not_found}
end
@doc """
Fetches a single result from the query. Returns an ok/error tuple.
"""
@spec fetch_by(Queryable.t(), keyword, keyword) ::
{:ok, Schema.t()} | {:error, :not_found}
def fetch_by(queryable, clauses, opts \\ []) do
case get_by(queryable, clauses, opts) do
nil -> {:error, :not_found}
something -> {:ok, something}
end
end
@doc """
Fetches a single result from the query. Returns an ok/error tuple.
"""
@spec fetch_one(Queryable.t(), keyword) ::
{:ok, Schema.t()} | {:error, :not_found}
def fetch_one(queryable, opts \\ []) do
case one(queryable, opts) do
nil -> {:error, :not_found}
something -> {:ok, something}
end
end
end
# example test module assuming there is an ex_machina factory and a user struct
defmodule MyApp.RepoTest do
use MyApp.DataCase, async: true
import MyApp.Factory
import Ecto.Query
alias MyApp.Accounts.User
alias MyApp.Repo
describe "fetch/3" do
test "returns a resource" do
user = insert(:user)
assert {:ok, %User{}} = Repo.fetch(User, user.id)
end
test "returns an error" do
assert {:error, :not_found} == Repo.fetch(User, 1)
end
end
describe "fetch_by/3" do
test "returns a resource" do
user = insert(:user)
assert {:ok, %User{}} = Repo.fetch_by(User, email: user.email)
end
test "returns an error" do
assert {:error, :not_found} == Repo.fetch_by(User, email: "[email protected]")
end
end
describe "fetch_one/3" do
test "returns a resource" do
%{email: email} = insert(:user)
assert {:ok, %User{}} =
User
|> where(email: ^email)
|> Repo.fetch_one()
end
test "returns an error" do
assert {:error, :not_found} ==
User
|> where(email: "[email protected]")
|> Repo.fetch_one()
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment