Repo.fetch/3
Every project I find myself writing the same bit of code.
I love to use case
and with
statements for conditional control flow across my code base and much prefer to
use ok/error tuples over pattern matching on nil
.
I find it weird that Ecto does not have this included in their API already, however luckily for us, it is easy to key in and extend the Repo module.
What I add to every Ecto project
We can use what Ecto gives us out of the box and just extend our Repo module with these two little wrapper functions.
defmodule MyApp.Repo do
use Ecto.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.Postgres
@spec fetch(Ecto.Queryable.t(), binary(), keyword()) ::
{:ok, Ecto.Schema.t()} | {:error, :not_found}
def fetch(queryable, id, opts \\ []) do
case get(queryable, id, opts) do
nil -> {:error, :not_found}
record -> {:ok, record}
end
end
@spec fetch_by(Ecto.Queryable.t(), keyword() | map(), keyword()) ::
{:ok, Ecto.Schema.t()} | {:error, :not_found}
def fetch_by(queryable, clauses, opts \\ []) do
case get_by(queryable, clauses, opts) do
nil -> {:error, :not_found}
record -> {:ok, record}
end
end
end
Now calling Repo.fetch/3
feels like a native Ecto implementation and we do
not ever need to worry about custom logic as we are just re-using what is
already there and passing on all the arguments.