Ben Keil
Ben Keil

Reputation: 1183

Error handling in Phoenix

I want to differentiate "page not found" and "resource not found" errors. Is it possible to get the exception type to do something like the following?

def render("404.json", assigns) do
  case assigns[:reason] do
    NoRouteErro -> message = "Route not found"
    Ecto.NoResultsError -> message = "Resource not found"
    _ -> message = "Uncaught exception"
  end
  ContactService.ResponseHelper.error(message)
end

Upvotes: 2

Views: 1370

Answers (1)

Dogbert
Dogbert

Reputation: 222138

You have that almost right; the patterns you're matching against are incorrect. To match the struct type of a struct with case (and ignore the value of any fields of the struct), you need to use a % before and {} after the struct's module name. You should also do the assignment outside the case to prevent Elixir's "unsafe variable" warning. I've also switched to pattern matching in the function head instead of using assigns[:reason].

Final code:

def render("404.json", %{reason: reason}) do
  message = case reason do
    %Phoenix.Router.NoRouteError{} -> "Route not found"
    %Ecto.NoResultsError{} -> "Resource not found"
    _ -> "Uncaught exception"
  end
  # ContactService.ResponseHelper.error(message)
  %{error: message}
end

With this code, I get the following results:

$ curl -H 'Accept: application/json' http://localhost:4000/404
{"error":"Route not found"}
$ curl -H 'Accept: application/json' http://localhost:4000/api/contacts/1
{"error":"Resource not found"}

Upvotes: 3

Related Questions