sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo generar un error de Postgresql personalizado y manejarlo en Ecto

Hasta donde yo sé, no existe un mecanismo integrado para manejar los errores personalizados de PostgreSQL. Sin embargo, puede hacerlo a nivel de repositorio.

Para hacer eso, debe generar errores en PostgreSQL usando ERRCODE como:

RAISE '[message for logs]' USING ERRCODE = 'integrity_constraint_violation';

y luego manejarlos en la aplicación:

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

Tenga en cuenta el {:error, %{changeset | valid?: false}} respuesta. Significa que en ese momento, no habrá ningún mensaje útil para mostrar.

PD:probablemente podría escribir algunas macros para anular las funciones de Ecto y ocultar la implementación allí (en lugar de la solución propuesta), pero creo que sería mucho más difícil de mantener.