は、私のような移行持っている:Phoenix guidelinesからの提案に続き複合キー、 `unique_constraint`問題
defmodule N.Auth do
use N.Web, :model
@primary_key false
schema "auths" do
field :oauth_id, :string, primary_key: true
field :provider, :string, primary_key: true
belongs_to :user, N.User
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:oauth_id, :provider])
|> validate_required([:oauth_id, :provider])
|> unique_constraint(:oauth_id, :auths_oauth_id_index)
end
end
:
defmodule N.Repo.Migrations.CreateAuth do
use Ecto.Migration
def change do
create table(:auths, primary_key: false) do
add :oauth_id, :string, primary_key: true
add :provider, :string, primary_key: true
add :user_id, references(:users, on_delete: :nothing, type: :binary_id)
timestamps()
end
create index(:auths, [:user_id])
end
end
とモデル次のように構成します。私のテストで
:
defmodule N.AuthTest do
use N.ModelCase
import N.Factory
alias N.Auth
test "changeset with duplicates" do
auth_params =
%{provider: :facebook,
oauth_id: "1234"}
insert(:auth, auth_params)
changeset = Auth.changeset(%Auth{}, auth_params)
assert {:error, changeset} = Repo.insert(changeset)
end
end
それらを実行している場合残念ながら、私はエラーを次ています
create unique_index(:auths, [:oauth_id, :provider])
:私はそれを正しく理解していれば
1) test N.Auth.changeset/2 changeset with duplicates (N.AuthTest)
test/models/auth_test.exs:31
** (FunctionClauseError) no function clause matching in Access.fetch/2
stacktrace:
(elixir) lib/access.ex:147: Access.fetch(:auths_oauth_id_index, :name)
(elixir) lib/access.ex:179: Access.get/3
(ecto) lib/ecto/changeset.ex:1629: Ecto.Changeset.unique_constraint/3
test/models/auth_test.exs:37: (test)
、これはが不足しているためであります
は、unique_constraint/3
の説明書に記載されています。明らかに、複合主キーを設定することによって自動的に作成されるので、インデックスを作成したくありません。
これ以上の対応方法はありますか?
UPDATE
ここで使用されるインデックス名はEcto
自体によって提案された - 私は、インデックス名を指定せずにコードを使用する場合、そのよう:
|> unique_constraint(:oauth_id)
私は、テストを実行すると、エラーを
1) test N.Auth.changeset/2 changeset with duplicates (N.AuthTest)
test/models/auth_test.exs:31
** (Ecto.ConstraintError) constraint error when attempting to insert struct:
* unique: auths_pkey
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: auths_oauth_id_index
stacktrace:
(ecto) lib/ecto/repo/schema.ex:403: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3
(elixir) lib/enum.ex:1183: Enum."-map/2-lists^map/1-0-"/2
(ecto) lib/ecto/repo/schema.ex:393: Ecto.Repo.Schema.constraints_to_errors/3
(ecto) lib/ecto/repo/schema.ex:193: anonymous fn/11 in Ecto.Repo.Schema.do_insert/4
(ecto) lib/ecto/repo/schema.ex:595: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6
(ecto) lib/ecto/adapters/sql.ex:472: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
(db_connection) lib/db_connection.ex:973: DBConnection.transaction_run/4
(db_connection) lib/db_connection.ex:897: DBConnection.run_begin/3
(db_connection) lib/db_connection.ex:671: DBConnection.transaction/3
test/models/auth_test.exs:41: (test)
私が試しているときに同じエラーが発生しますcheck_constraint/3
、のように:それはキー:name
とキーワードリスト項目にする必要のに対し
|> check_constraint(:oauth_id, name: :auths_oauth_id_index)
てみ 'unique_constraint(:oauth_id、名前:auths_pkey)'。それがうまくいかない場合は、 ':auths_pkey'を作成された実際のインデックスの名前で置き換えてください。それが動作すれば、私は説明を投稿します。 – Dogbert
こんにちは@Dogbert、あなたの提案に感謝!これはまさにこれまで私がやったことです。私があなたが示唆したようにすると、エラーメッセージはほぼ同じままです。 '(elixir)lib/access.ex:147:Access。fetch(:auths_pkey、:name) 'を実行します。私は 'auths_oauth_id_index'に行ったもう少しの情報で私の質問を更新しました –
' |> unique_constraint(:oauth_id、name::auths_pkey) 'がうまくいきませんか?これを追加した後にサーバーを再起動できますか? – Dogbert