Até onde eu sei, não existe um mecanismo embutido para lidar com erros personalizados do PostgreSQL. No entanto, você pode fazer isso no nível do repositório.
Para fazer isso, você deve gerar erros no PostgreSQL usando
ERRCODE
Curti:RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';
e, em seguida, trate-os no aplicativo:
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
Observe o
{:error, %{changeset | valid?: false}}
resposta. Isso significa que, nesse ponto, não haverá nenhuma mensagem útil para exibir. PS você provavelmente poderia escrever algumas macros para substituir as funções do Ecto e ocultar a implementação lá (em vez da solução proposta), mas acredito que seria muito mais difícil de manter.