cnck1387
Why does Repo.get and Repo.get_by return the resource or nil instead of an ok or error tuple?
Hi,
Repo.insert, Repo.update and Repo.delete all return {:ok, resource} or {:error, changeset}.
But Repo.get and Repo.get_by return resource or nil.
I also noticed a decent amount of custom code (such as the Programming Phoenix Rumbl example app) prefers to use the tuple style, such as the RumblWeb.Auth.login_by_email_and_pass function returning {:ok, conn} or {:error, _reason, conn}.
That made me very curious. Why doesn’t Repo.get return {:ok, resource} or {:error, :resource_not_found}?
If it’s an API oversight and too late to change, what do you think about adding this custom function to your lib/myapp/repo.ex and always using this instead of get_by?
def fetch_by(queryable, clauses, opts \\ []) do
case get_by(queryable, clauses, opts) do
nil ->
{:error, :resource_not_found}
resource ->
{:ok, resource}
end
end
The fetch function (not included here) would do the same thing, except wrap get.
Edit: For clarity, it would be useful to have this because when pattern matching on else when using with it’s a lot more obvious to see what went wrong when you match on something like {:error, :resource_not_found} vs matching on nil.
Most Liked
benwilson512
Yup. I add this to all my apps repo modules usually:
def fetch(query) do
case all(query) do
[] -> {:error, query}
[obj] -> {:ok, obj}
_ -> raise "Expected one or no items, got many items #{inspect(query)}"
end
end
Super handy when you use with as well.
benwilson512
Ah well I actually have three functions:
def fetch_by(query, args) do
query
|> where(^args)
|> fetch
end
def fetch(query, id) do
query
|> where(id: ^id)
|> fetch
end
def fetch(query) do
case all(query) do
[] -> {:error, query}
[obj] -> {:ok, obj}
_ -> raise "Expected one or no items, got many items #{inspect(query)}"
end
end
benwilson512
Yeah there’s a reason my fetch uses all internally because you can also run into issues if your query selects just one column which can be nil.
value = User |> select([u], u.banned_at) |> Repo.get(id)
If value is nil, was the user never banned? or do they not exist? The fetch function I wrote will return {:ok, nil} for a user that exists but the column is nil, and {:error, query} if they don’t exist at all.
I proposed it to the ecto team a while ago, you can find the discussion here: Repo.get returns ambiguous responses · Issue #1225 · elixir-ecto/ecto · GitHub
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance










