I’m trying to change the values of some fields to camelCase with middleware like this:
defmodule Middlewares.CamelCaseField do
@behaviour Absinthe.Middleware
def call(resolution, _) do
%{resolution | errors: Enum.flat_map(resolution.errors, &handle_error/1)}
end
defp handle_error(%{field: field} = error) do
%{error | field: camel(field)}
end
defp handle_error([]), do: []
defp handle_error(error) when is_list(error) do
case Keyword.get(error, :field) do
nil -> error
field -> Keyword.put(error, :field, camel(field))
end
end
defp handle_error(error), do: [error]
def camel(f), do: Atom.to_string(f) |> Recase.to_camel()
end
...
defmodule Schema do
....
def middleware(middleware, field, object) do
middleware ++ [Middlewares.CamelCaseField]
end
But now when I run my code I get errors like these:
** (Protocol.UndefinedError) protocol String.Chars not implemented for {:code, :unknown_error}. This protocol is implemented for: Postgrex.Copy, Postgrex.Query, Decimal, DateTime, Date, Version, NaiveDateTime, List, Atom, Time, BitString, Integer, URI, Version.Requirement, Float
.
If I remove my middleware everything works, so I’m probably doing something wrong with the middleware, but don’t know what exactly.
Found my mistake. I needed to wrap the result of handle_error(error) when is_list(error)
in a list as well, so:
defp handle_error(error) when is_list(error) do
error = case Keyword.get(error, :field) do
nil -> error
field -> Keyword.put(error, :field, camel(field))
end
[error]
end
3 Likes
@tcoopman Have you tried Absinthe.Adapter.LanguageConventions ( https://github.com/absinthe-graphql/absinthe/blob/master/guides/adapters.md) ?
You have to add this configuration in your config.exs
file. Example:
config :absinthe, adapter: Absinthe.Adapter.LanguageConventions
I’m using it and works very fine.
Note that you can no longer set the adapter in the configuration, but instead need to do it in the router: https://github.com/absinthe-graphql/absinthe/pull/575
1 Like
or in the endpoint.ex when the entire API is base on GraphQL
plug Absinthe.Plug,
schema: ContentProxyGraphql.Schema,
adapter: Absinthe.Adapter.LanguageConventions,
json_codec: Jason
I’m not sure the adapter can help translating values in error results? If I have %{errors: [%{field: "my_field"}]}
translate the my_field
value to myField
?
hum… probably I misunderstood your question
The LanguageConventions adapter only changes the field name case.
However, in my opinion, sounds strange to change user values in output moment, except for date format or enumeration values.
If your values are statics, perhaps would be more expressive to use Graphl Enum (absinthe/guides/tutorial/complex-arguments.md at main · absinthe-graphql/absinthe · GitHub)
If enum doesn’t fit your needs, the code you have made is nice!
my use case is that I let use ecto changeset to validate parts of the code. But this returns fields in snake case. So before I send it to the user if map my errors into output that is more consistent with the input query.
You can access the adapter within the third argument to the resolution function, so you could use that adapter’s to_external_name
function on your own error information to do the transformation.
1 Like