Ecto unique_constraint работает не так, как ожидалось

#elixir #ecto

#elixir #ecto

Вопрос:

Я хочу создать unique_constraint с 3 полями и назвать его «unique_user_product_shop». Когда я делаю это, моя база данных выдает сообщение об ошибке, в котором говорится, что попытка вставки не была уникальной:

ошибка:

 18:04:18.830 [error] #PID<0.380.0> running Api.Router terminated
Server: 192.168.1.12:4000 (http)
Request: PUT /product/isinshop/?p_id=12amp;s_id=12amp;u_id=792200324272726
** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in Ecto.Changeset.add_constraint/6
        (ecto) lib/ecto/changeset.ex:2272: Ecto.Changeset.add_constraint(#Ecto.Changeset<action: nil, changes: %{p_id: 12, s_id: 12, u_id: "792200324272726", voted_in_shop: true, voted_not_in_shop: false}, errors: [], data: #Api.UserProductShop<>, valid?: true>, :unique, "unique_user_product_shop", :exact, [:p_id, :u_id, :s_id], {"has already been taken", []})
        (api) lib/api/models/user_product_shop.ex:37: Api.UserProductShop.insert_user_product_shop/2
        (api) lib/api/controllers/product/put_product_is_in_shop.ex:48: Api.Controllers.PutProductIsInShop.put_product_is_in_shop/1
        (api) lib/api/router.ex:1: Api.Router.plug_builder_call/2
        (api) lib/plug/debugger.ex:123: Api.Router.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /Users/Ben/Development/Projects/vepo/api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
  

мой код:

   def changeset(user_product_shop, params \ %{}) do
    user_product_shop
    |> cast(params, [
        :u_id, 
        :p_id,
        :s_id,
        :voted_not_in_shop,
        :voted_in_shop])
    |> validate_required([:u_id, :p_id, :s_id])
    |> unique_constraint([:p_id, :u_id, :s_id], name: :unique_user_product_shop)
  end
  

Итак, почему он не распознает мой unique_constraint, из-за чего моя база данных выдает красную ошибку в консоли?

Комментарии:

1. Ваш код взорван в вашей функции набора изменений. Это даже не попадает в базу данных. Я не верю, что это unique_constraint может принимать массив полей. Вы должны добавить ошибку в одно поле или в :base . Документы: hexdocs.pm/ecto/Ecto. Набор изменений.html#unique_constraint/3

Ответ №1:

Ecto.Changeset.unique_constraint/3 необходимо создать резервную копию с помощью реального ограничения уникальности в базе данных. Вот выдержка из документации:

Чтобы использовать ограничение уникальности, первым шагом является определение уникального индекса при миграции:

 create unique_index(:users, [:email])
  

Ecto.Changeset.unique_constraint/3 создается так, чтобы шаблон соответствовал только существующим уникальным ограничениям, поэтому, если в базе данных нет такого ограничения, FunctionClauseError возникает.