API raise exception instead of returning []

Hello.

I am fairly new to Phoenix/elixir, but I read the doc and couldn’t find what I was looking for.
I am currently working on a basic Phoenix API. After studying a bit the Ecto documentation, I found the lines about Ecto.get and get_by, which helped me adding new endpoints to request the database with another argument than the id.

Now, I am stuck, because when I request some id which isn’t on the API, it raise a error " Ecto.NoResultsError". What I want is a empty data, or nil, so my other program can check if there is content matching the request.

I undestand the Exception came from the Repo.get, so I tried to rewrite my show function in the controller like that :

def show(conn, %{"accession_number" => accession_number}) do
    try do
      dicom = DICOM.get_dicom_an!(accession_number)
      render(conn, "show.json", dicom: dicom)
    rescue
      e in RuntimeError -> IO.puts(e.message)
      render(conn, "show.json", "")
    end
  end

However, I couldn’t get it to work. I also tried to pattern match
with error in the delete function, but I couldn’t make it work.

What is the way to achieve what I want ?

try and rescue are not the usual way of dealing with errors.

There is a difference between functions with or without !

One raise, the other returns nil, which is what You want.

Ok thanks for your time. The thing worked for get_dicom_an, however when I tried to do so for the get_dicom (Which work with id and call Repo.get), it raised a Ecto.Query.CastError.

When I use the information from the error page, I can see that for the Ecto Queyable session :

def one(name, queryable, opts) do
    case all(name, queryable, opts) do
      [one] -> one
      [] -> nil
      other -> raise Ecto.MultipleResultsError, queryable: queryable, count: length(other)
    end
  end

So I think I called correctly my function, as [] returns nil, and doesn’t raise exception, however, in that case why does it work with get_dicom_an and not with get_dicom ?

Is there some difference I failed to grasp between Repo.get and Repo.get_by ?

You probably forgot to transform id (as a string) to integer…

And You are probably using integer id, not binary id.

Sorry but I don’t get it.

Everything work fine when I use a valid id, so I don’t get where a cast problem can occur. Can you tell me where in my execution flow I should cast.

I tried using String.to_integer at 2 places, when calling get_dicom and when calling Repo.get, but it couldn’t work. id are auto-generated, and they are string with letters. Exemple “b416bab4-e526-49cd-8109-45aed0baeae3”. So I truly don’t get why should I cast to integer.

I even tried to use Repo.get_by(Dicom, id: id) but it failed too

This usually means You do not provide the right casting type…

If You use binary_id, there is no need to turn id into integer.

Ok, I get the error, it something I’ve looked up.

What I don’t undestand is why it happen in that case, what can I do, and why does the whole work when I use a valid id.

I checked my PostGRES and my id column is of type uuid (autogenerated). My exception also said :

value `"b416bab4-e526-49cd-8109-45aed0baee3"` cannot be dumped to type :binary_id in query:

So, I think I am not using an integer id. What am I missing ?

1 Like