mirror of
https://github.com/ash-project/ash_phoenix.git
synced 2024-09-20 07:12:49 +12:00
improvement: readability refactor + additional docs
This commit is contained in:
parent
3711c98763
commit
0bb2216147
2 changed files with 139 additions and 51 deletions
|
@ -1,8 +1,9 @@
|
|||
defmodule AshPhoenix do
|
||||
@moduledoc """
|
||||
See the readme for the current state of the project
|
||||
Various helpers and utilities for working with Ash changesets and queries and phoenix.
|
||||
"""
|
||||
|
||||
@doc false
|
||||
def to_form_error(exception) when is_exception(exception) do
|
||||
case AshPhoenix.FormData.Error.to_form_error(exception) do
|
||||
nil ->
|
||||
|
@ -27,12 +28,144 @@ defmodule AshPhoenix do
|
|||
end
|
||||
end
|
||||
|
||||
def transform_errors(changeset, transform_errors) do
|
||||
@doc """
|
||||
Allows for manually transforming errors to modify or enable error messages in the form.
|
||||
|
||||
By default, only errors that implement the `AshPhoenix.FormData.Error` protocol will show
|
||||
their errors in forms. This is to protect you from showing strange errors to the user. Using
|
||||
this function, you can intercept those errors (as well as ones that *do* implement the protocol)
|
||||
and return custom form-ready messages for them.
|
||||
|
||||
Example:
|
||||
|
||||
AshPhoenix.transform_errors(changeset, fn changeset, %MyApp.CustomError{message: message} ->
|
||||
{:id, "Something went wrong while doing the %{thing}", [thing: "request"]}
|
||||
end)
|
||||
|
||||
# Could potentially be used for translation, although not quite ergonomic yet
|
||||
defp translate_error(key, msg, vars) do
|
||||
if vars[:count] do
|
||||
Gettext.dngettext(MyApp.Gettext, "errors", msg, msg, count, opts)
|
||||
else
|
||||
Gettext.dgettext(MyApp.Gettext, "errors", msg, opts)
|
||||
end
|
||||
end
|
||||
|
||||
AshPhoenix.transform_errors(changeset, fn
|
||||
changeset, %MyApp.CustomError{message: message, field: field} ->
|
||||
translate_error(field, message, [foo: :bar])
|
||||
|
||||
changeset, any_error ->
|
||||
if AshPhoenix.FormData.Error.impl_for(any_error) do
|
||||
any_error
|
||||
|> AshPhoenix.FormData.error.to_form_error()
|
||||
|> List.wrap()
|
||||
|> Enum.map(fn {key, msg, vars} ->
|
||||
translate_error(key, msg, vars)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
"""
|
||||
@spec transform_errors(
|
||||
Ash.Changeset.t() | Ash.Query.t(),
|
||||
(Ash.Query.t() | Ash.Changeset.t(), error :: Ash.Error.t() ->
|
||||
[{field :: atom, message :: String.t(), substituations :: Keyword.t()}])
|
||||
) :: Ash.Query.t() | Ash.Changeset.t()
|
||||
def transform_errors(%Ash.Changeset{} = changeset, transform_errors) do
|
||||
Ash.Changeset.put_context(changeset, :private, %{
|
||||
ash_phoenix: %{transform_errors: transform_errors}
|
||||
})
|
||||
end
|
||||
|
||||
def transform_errors(%Ash.Query{} = changeset, transform_errors) do
|
||||
Ash.Query.put_context(changeset, :private, %{
|
||||
ash_phoenix: %{transform_errors: transform_errors}
|
||||
})
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets all errors on a changeset or query.
|
||||
|
||||
This honors the AshPhoenix.FormData.Error` protocol and applies any `transform_errors`.
|
||||
See `transform_errors/2` for more information.
|
||||
"""
|
||||
@spec errors_for(Ash.Changeset.t() | Ash.Query.t(), Keyword.t()) ::
|
||||
[{atom, {String.t(), Keyword.t()}}] | [String.t()] | map
|
||||
def errors_for(changeset_or_query, opts \\ []) do
|
||||
errors =
|
||||
if hiding_errors?(changeset_or_query) do
|
||||
[]
|
||||
else
|
||||
changeset_or_query.errors
|
||||
|> Enum.filter(fn
|
||||
error when is_exception(error) ->
|
||||
AshPhoenix.FormData.Error.impl_for(error)
|
||||
|
||||
{_key, _value, _vars} ->
|
||||
true
|
||||
|
||||
_ ->
|
||||
false
|
||||
end)
|
||||
|> Enum.flat_map(&transform_error(changeset_or_query, &1))
|
||||
|> Enum.map(fn {field, message, vars} ->
|
||||
{field, {message, vars}}
|
||||
end)
|
||||
end
|
||||
|
||||
case opts[:as] do
|
||||
raw when raw in [:raw, nil] ->
|
||||
errors
|
||||
|
||||
:simple ->
|
||||
Map.new(errors, fn {field, {message, vars}} ->
|
||||
message =
|
||||
Enum.reduce(vars || [], message, fn {key, value}, acc ->
|
||||
String.replace(acc, "%{#{key}}", to_string(value))
|
||||
end)
|
||||
|
||||
{field, message}
|
||||
end)
|
||||
|
||||
:plaintext ->
|
||||
Enum.map(errors, fn {field, {message, vars}} ->
|
||||
message =
|
||||
Enum.reduce(vars || [], message, fn {key, value}, acc ->
|
||||
String.replace(acc, "%{#{key}}", to_string(value))
|
||||
end)
|
||||
|
||||
"#{field}: " <> message
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defp transform_error(_query, {_key, _value, _vars} = error), do: error
|
||||
|
||||
defp transform_error(query, error) do
|
||||
case query.context[:private][:ash_phoenix][:transform_error] do
|
||||
transformer when is_function(transformer, 2) ->
|
||||
case transformer.(query, error) do
|
||||
error when is_exception(error) ->
|
||||
List.wrap(AshPhoenix.to_form_error(error))
|
||||
|
||||
{key, value, vars} ->
|
||||
[{key, value, vars}]
|
||||
|
||||
list when is_list(list) ->
|
||||
Enum.flat_map(list, fn
|
||||
error when is_exception(error) ->
|
||||
List.wrap(AshPhoenix.to_form_error(error))
|
||||
|
||||
{key, value, vars} ->
|
||||
[{key, value, vars}]
|
||||
end)
|
||||
end
|
||||
|
||||
nil ->
|
||||
List.wrap(AshPhoenix.to_form_error(error))
|
||||
end
|
||||
end
|
||||
|
||||
def hide_errors(%Ash.Changeset{} = changeset) do
|
||||
Ash.Changeset.put_context(changeset, :private, %{ash_phoenix: %{hide_errors: true}})
|
||||
end
|
||||
|
|
|
@ -23,52 +23,7 @@ defmodule AshPhoenix.FormData.Helpers do
|
|||
end
|
||||
|
||||
def form_for_errors(query, _opts) do
|
||||
if AshPhoenix.hiding_errors?(query) do
|
||||
[]
|
||||
else
|
||||
query.errors
|
||||
|> Enum.filter(fn
|
||||
error when is_exception(error) ->
|
||||
AshPhoenix.FormData.Error.impl_for(error)
|
||||
|
||||
{_key, _value, _vars} ->
|
||||
true
|
||||
|
||||
_ ->
|
||||
false
|
||||
end)
|
||||
|> Enum.flat_map(&transform_error(query, &1))
|
||||
|> Enum.map(fn {field, message, vars} ->
|
||||
{field, {message, vars}}
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defp transform_error(_query, {_key, _value, _vars} = error), do: error
|
||||
|
||||
defp transform_error(query, error) do
|
||||
case query.context[:private][:ash_phoenix][:transform_error] do
|
||||
transformer when is_function(transformer, 2) ->
|
||||
case transformer.(query, error) do
|
||||
error when is_exception(error) ->
|
||||
List.wrap(AshPhoenix.to_form_error(error))
|
||||
|
||||
{key, value, vars} ->
|
||||
[{key, value, vars}]
|
||||
|
||||
list when is_list(list) ->
|
||||
Enum.flat_map(list, fn
|
||||
error when is_exception(error) ->
|
||||
List.wrap(AshPhoenix.to_form_error(error))
|
||||
|
||||
{key, value, vars} ->
|
||||
[{key, value, vars}]
|
||||
end)
|
||||
end
|
||||
|
||||
nil ->
|
||||
List.wrap(AshPhoenix.to_form_error(error))
|
||||
end
|
||||
AshPhoenix.errors_for(query)
|
||||
end
|
||||
|
||||
def form_for_name(resource) do
|
||||
|
@ -175,9 +130,9 @@ defmodule AshPhoenix.FormData.Helpers do
|
|||
if update_action do
|
||||
Ash.Changeset.for_update(data, update_action.name, %{})
|
||||
else
|
||||
resource
|
||||
|> Ash.Changeset.new(data)
|
||||
|> Map.put(:params, data)
|
||||
data
|
||||
|> Ash.Changeset.new()
|
||||
|> Map.put(:params, %{})
|
||||
end
|
||||
|
||||
is_nil(data) ->
|
||||
|
|
Loading…
Reference in a new issue