Created
August 10, 2020 13:13
-
-
Save jherdman/d6c89166d4d427108629ec3d1618d199 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule RovrApiWeb.ChangesetView do | |
use RovrApiWeb, :view | |
@doc """ | |
Traverses and translates changeset errors. | |
See `Ecto.Changeset.traverse_errors/2` and | |
`RovrApiWeb.ErrorHelpers.translate_error/1` for more details. | |
""" | |
def translate_errors(changeset) do | |
Ecto.Changeset.traverse_errors(changeset, &translate_error/1) | |
end | |
@doc ~S""" | |
Converts a map of errors into a JSON:API collection of error objects | |
## Examples | |
iex> jsonapi_error_objects(%{name: ["can't be blank"], url: ["can't be blank"]}) | |
[ | |
%{ | |
"title" => "can't be blank", | |
"source" => %{"pointer" => "/data/attributes/name"} | |
}, | |
%{ | |
"title" => "can't be blank", | |
"source" => %{"pointer" => "/data/attributes/url"} | |
} | |
] | |
iex> jsonapi_error_objects(%{feed_id: ["does not exist"]}) | |
[ | |
%{ | |
"title" => "does not exist", | |
"source" => %{"pointer" => "/data/relationships/feed"} | |
} | |
] | |
""" | |
@spec jsonapi_error_objects(errors :: map()) :: [map()] | |
def jsonapi_error_objects(errors) do | |
errors | |
|> Enum.map(fn {attr, errs} -> | |
{get_pointer(attr), errs} | |
end) | |
|> Enum.flat_map(fn {pointer, errs} -> | |
Enum.map(errs, fn err -> | |
%{ | |
"title" => err, | |
"source" => %{ | |
"pointer" => pointer | |
} | |
} | |
end) | |
end) | |
end | |
defp get_pointer(attr) when is_atom(attr), do: get_pointer(Atom.to_string(attr)) | |
defp get_pointer(attr) do | |
attr = JSONAPI.Utils.String.camelize(attr) | |
if String.ends_with?(attr, "Id") do | |
attr = String.replace_trailing(attr, "Id", "") | |
"/data/relationships/#{attr}" | |
else | |
"/data/attributes/#{attr}" | |
end | |
end | |
def render("error.json", %{changeset: changeset}) do | |
errors = | |
changeset | |
|> translate_errors() | |
|> jsonapi_error_objects() | |
# When encoded, the changeset returns its errors | |
# as a JSON object. So we just pass it forward. | |
%{errors: errors} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment