diff --git a/lib/ash/actions/update/update.ex b/lib/ash/actions/update/update.ex index bdfa5654..96e638dc 100644 --- a/lib/ash/actions/update/update.ex +++ b/lib/ash/actions/update/update.ex @@ -271,6 +271,8 @@ defmodule Ash.Actions.Update do with %{valid?: true} = changeset <- Ash.Changeset.validate_multitenancy(changeset), %{valid?: true} = changeset <- changeset(changeset, domain, action, opts), %{valid?: true} = changeset <- authorize(changeset, opts), + %{valid?: true} = changeset <- + Ash.Changeset.add_atomic_validations(changeset, opts[:actor], []), {:ok, result, instructions} <- commit(changeset, domain, opts) do add_notifications( changeset.resource, diff --git a/lib/ash/error/error.ex b/lib/ash/error/error.ex index 8b6e4d0e..124a3460 100644 --- a/lib/ash/error/error.ex +++ b/lib/ash/error/error.ex @@ -86,6 +86,26 @@ defmodule Ash.Error do end end + def error_descriptions(errors) do + errors + |> to_error_class() + |> Map.get(:errors) + |> Enum.group_by(& &1.class) + |> Enum.sort_by(fn {group, _} -> + Enum.find_index([:forbidden, :invalid, :framework, :unknown], &(&1 == group)) + end) + |> Enum.map_join("\n\n", fn {class, class_errors} -> + header = header(class) <> "\n\n" + + header <> Enum.map_join(class_errors, "\n", &"* #{Exception.message(&1)}") + end) + end + + defp header(:forbidden), do: "Forbidden" + defp header(:invalid), do: "Input Invalid" + defp header(:framework), do: "Framework Error" + defp header(:unknown), do: "Unknown Error" + def ash_error?(value), do: splode_error?(value, __MODULE__) def set_path(%struct{errors: errors} = container, path)