Ecto.NoResultsError render json

I have the following controller in API which uses Phoenix.

defmodule TattooBackend.Web.API.V1.StudioController do
  use TattooBackend.Web, :controller

  alias TattooBackend.Accounts.Studio

  def show(conn, %{"id" => id}) do
    studio = Repo.get!(Studio, id)

    render conn, studio: studio
  end
end

My goal here is to rescue globally Ecto.NoResultsError and render some error message. I can rewrite this into following format:

def show(conn,%{"id" => id}) do
  case Repo.get(Studio, id) do
    nil -> # return null and 404 
    record -> # do something with record        
  end
end

but I want to avoid repeating this pattern in other controllers. How can I solve this problem?

1 Like

I believe it is already solved, and your original code should work just fine.

When Repo.get! fails it raises Ecto.NoResultsError as you may understand, and the phoenix_ecto library already handles this error as 404.

In your app, you can handle this error at error_view.ex. You should be having a function render('404.json', _assigns) generated when you do mix phoenix.new.

Note: the render('404.json', _assigns) is only called when you’re running in Mix.env == :prod. If the env is :dev, you’ll be seeing Phoenix error page instead (but with the correct 404 status).

2 Likes

Just incase any other person has this issue, you could try:

  • Add the following to your config/config.exs file
config :my_app, MyApp.Endpoint,
  # ...
  render_errors: [accepts: ~w(html json)],
  # ...
  • Disable debug_errors in you config/dev.exs file
config :my_app, MyApp.Endpoint,
  # ...
  debug_errors: false,
  # ...

Credit: Thanks to Ole for his answer on Stackoverflow, https://stackoverflow.com/a/36334954

3 Likes