Доколкото знам, няма вграден механизъм за обработка на персонализирани грешки на PostgreSQL. Можете обаче да го направите на ниво хранилище.
За да направите това, трябва да генерирате грешки в PostgreSQL, като използвате ERRCODE
като:
RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';
и след това да ги обработвате в приложението:
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
Обърнете внимание на {:error, %{changeset | valid?: false}}
отговор. Това означава, че в този момент няма да има полезно съобщение за показване.
PS вероятно бихте могли да напишете някои макроси, за да замените функциите на Ecto и да скриете имплементацията там (вместо предложеното решение), но вярвам, че ще бъде много по-трудно да се поддържа.