Autant que je sache, il n'y a pas de mécanisme intégré pour gérer les erreurs personnalisées de PostgreSQL. Cependant, vous pouvez le faire au niveau du référentiel.
Pour ce faire, vous devez générer des erreurs dans PostgreSQL en utilisant ERRCODE
comme :
RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';
puis les gérer dans l'application :
defmodule Core.Repo do
use Ecto.Repo, otp_app: :core
defoverridable insert: 2
def insert(changeset, opts) do
super(changeset, opts)
rescue
exception in Postgrex.Error ->
handle_postgrex_exception(exception, __STACKTRACE__, changeset)
end
# ... other functions
defp handle_postgrex_exception(exception, stacktrace, changeset \\ nil)
defp handle_postgrex_exception(%{postgres: %{code: :integrity_constraint_violation}}, _, nil) do
{:error, :integrity_constraint_violation}
end
defp handle_postgrex_exception(
%{postgres: %{code: :integrity_constraint_violation}},
_,
changeset
) do
{:error, %{changeset | valid?: false}}
end
defp handle_postgrex_exception(exception, stacktrace, _) do
reraise(exception, stacktrace)
end
end
Notez le {:error, %{changeset | valid?: false}}
réponse. Cela signifie qu'à ce stade, il n'y aura plus de message utile à afficher.
PS, vous pourriez probablement écrire des macros pour remplacer les fonctions d'Ecto et y masquer l'implémentation (au lieu de la solution proposée) mais je pense que ce serait beaucoup plus difficile à maintenir.