Search code examples
elixirecto

stop ecto from throwing unique constraint error


I keep getting this error. The error is expected, but how can I handle the case so that it doesn't throw red text in the console?

code:

  def insert_user_product(conn, user_product) do
    changeset = Api.UserProduct.changeset(%Api.UserProduct{}, user_product)
    errors = changeset.errors
    valid = changeset.valid?
    case insert(changeset) do
      {:ok, user_product} ->
        {:ok, user_product}
      {:error, changeset} ->
        {:error, :failure}
    end
  end

error:

14:23:18.273 [error] #PID<0.354.0> running Api.Router terminated
Server: 172.20.10.6:4000 (http)
Request: PUT /product/isvegan/?p_id=1&u_id=792200324272726
** (exit) an exception was raised:
    ** (Ecto.ConstraintError) constraint error when attempting to insert struct:

    * unique: unique_user_product

If you would like to convert this constraint into an error, please
call unique_constraint/3 in your changeset and define the proper
constraint name. The changeset defined the following constraints:

    * unique: user_products_p_id_index

        (ecto) lib/ecto/repo/schema.ex:574: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3
        (elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
        (ecto) lib/ecto/repo/schema.ex:559: Ecto.Repo.Schema.constraints_to_errors/3
        (ecto) lib/ecto/repo/schema.ex:222: anonymous fn/14 in Ecto.Repo.Schema.do_insert/4
        (api) lib/api/models/user_product.ex:38: Api.UserProduct.insert_user_product/2
        (api) lib/api/controllers/product/put_product_is_vegan.ex:29: Api.Controllers.PutProductIsVegan.put_product_is_vegan/1
        (api) lib/api/router.ex:1: Api.Router.plug_builder_call/2
        (api) lib/plug/debugger.ex:123: Api.Router.call/2

Solution

  • Like the error message says you need to define a unique_constraint/3 in your changeset function so ecto can catch the error before the DB throws that error.

    defmodule Api.UserProduct do
    
    ....
    
      def changeset(struct, attrs) do
        struct
        |>cast(attrs, [...])
        |>validate_required([...])
        # Add this line
        |>unique_constraint(:p_id, message: "User product id already exists")
      end
    
    
    end