尝试构建数据库时出现 Phoenix unique_constraint 错误

cgg*_*cgg 3 elixir ecto phoenix-framework

我正在阅读 Phoenix 1.4 书,当我尝试通过终端将数据输入数据库时​​,我进入“使用存储库数据”部分,但出现错误。

\n\n

我的 IEx 会话:

\n\n
iex(1)> alias Rumbl.Repo\nRumbl.Repo\niex(2)> alias Rumbl.Accounts.User\nRumbl.Accounts.User\niex(3)> Repo.insert(%User{\n...(3)> name: "Jos\xc3\xa9", username: "josevalim"\n...(3)> })\n[debug] QUERY ERROR db=16.7ms queue=1.2ms\nINSERT INTO "users" ("name","username","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["Jos\xc3\xa9", "josevalim", ~N[2018-11-24 11:47:30], ~N[2018-11-24 11:47:30]]\n
Run Code Online (Sandbox Code Playgroud)\n\n

它引发了以下错误:

\n\n
** (Ecto.ConstraintError) constraint error when attempting to insert struct:\n\n    * users_username_index (unique_constraint)\n\nIf you would like to stop this constraint violation from raising an\nexception and instead add it as an error to your changeset, please\ncall `unique_constraint/3` on your changeset with the constraint\n`:name` as an option.\n\nThe changeset has not defined any constraint.\n\n    (ecto) lib/ecto/repo/schema.ex:641: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3\n    (elixir) lib/enum.ex:1314: Enum."-map/2-lists^map/1-0-"/2\n    (ecto) lib/ecto/repo/schema.ex:626: Ecto.Repo.Schema.constraints_to_errors/3\n    (ecto) lib/ecto/repo/schema.ex:238: anonymous fn/15 in Ecto.Repo.Schema.do_insert/3\n
Run Code Online (Sandbox Code Playgroud)\n

She*_*yar 7

看来您在表迁移中创建了唯一索引users

\n\n

约束位于您的username键上,这意味着表中的两条记录users不能具有相同的用户名。就您而言,这意味着您已经使用用户名在表中创建了另一个用户josevalim

\n\n
\n\n

要让 Ecto 返回{:error, changeset}元组而不是引发错误,您可以告诉模式changeset/2元组而不是引发错误,您可以告诉架构您的方法

\n\n\n\n
def changeset(user, params) do\n  user\n  |> cast(params, [:name, :username])\n  |> validate_required([:name, :username])\n  |> unique_constraint(:username, name: :users_username_index)\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

并在插入任何内容之前使用此方法构建变更集:

\n\n
%User{}\n|> changeset(%{name: "Jos\xc3\xa9", username: "josevalim"})\n|> Repo.insert\n
Run Code Online (Sandbox Code Playgroud)\n

  • 我想补充一点,`:name` 选项必须与 Ecto 生成的索引名称匹配。 (3认同)