gpt4 book ai didi

elixir - 唯一索引约束在 Phoenix 应用程序中不起作用

转载 作者:行者123 更新时间:2023-12-04 00:49:40 25 4
gpt4 key购买 nike

在我的 Phoenix 应用程序中,我的用户模型如下:

defmodule MyApp.User do
use MyApp.Web, :model

schema "users" do
field :username, :string, unique: true
field :email, :string, unique: true
field :crypted_password, :string
field :password, :string, virtual: true

timestamps
end

@required_fields ~w(email password username)
@optional_fields ~w()

@doc """
Creates a changeset based on the `model` and `params`.

If no params are provided, an invalid changeset is returned
with no validation performed.
"""
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
|> unique_constraint(:email)
|> unique_constraint(:username)
|> validate_format(:email, ~r/@/)
|> validate_length(:password, min: 5)
end
end

我也有以下迁移:
defmodule MyApp.Repo.Migrations.CreateUser do
use Ecto.Migration

def change do
create table(:users) do
add :email, :string
add :username, :string
add :crypted_password, :string

timestamps
end

create unique_index(:users, [:email])
create unique_index(:users, [:username])
end
end

我有我的 registration_controller_ex如下:
defmodule MyApp.RegistrationController do
use MyApp.Web, :controller
alias MyApp.User

def new(conn, _params) do
changeset = User.changeset(%User{})
render conn, changeset: changeset
end

def create(conn, %{"user" => user_params}) do
changeset = User.changeset(%User{}, user_params)

if changeset.valid? do
user = MyApp.Registration.create(changeset, MyApp.Repo)
conn
|> put_flash(:info, "Your account was created")
|> redirect(to: "/")
else
conn
|> put_flash(:info, "Unable to create account")
|> render("new.html", changeset: changeset)
end
end
end

所以,尽管如此,我很确定我的 usernameemail User 中的字段是唯一索引。我还通过调用 unique_constraint 来确保它们是独一无二的。验证 User.changeset。但是,当我在我的界面中创建一个与以前创建的用户具有相同电子邮件和用户名的用户时,变更集被验证并且用户被“创建”。 (它实际上并没有创建,当我查看数据库时没有添加任何内容)

我在服务器日志中得到以下信息,但我的 changeset.valid?是真的。
[debug] BEGIN [] OK query=139.3ms queue=8.2ms
[debug] INSERT INTO "users" ("crypted_password", "email", "inserted_at", "updated_at", "username") VALUES ($1, $2, $3, $4, $5) RETURNING "id" ["$2b$12$MN1YxFUGLMIJYXseZn0sjuuVs9U1jRdYtRr9D8XQsAqdh.D2sRRXa", "email@gmail.com", {{2015, 9, 30}, {11, 7, 25, 0}}, {{2015, 9, 30}, {11, 7, 25, 0}}, "username"] ERROR query=5.5ms
[debug] ROLLBACK [] OK query=0.4ms

此外,我在 User.changeset 函数中查找的其他内容(例如最小密码长度和其他内容)会报告给用户并且工作正常。这只是 :email 的唯一索引和 :username那些没有被报告的。

最佳答案

unique_constraint将由数据库检查,因此仅在插入记录时触发。调用changeset.valid?不会检查约束,因此在这种情况下返回 true。您需要检查 Repo 插入的返回元组并对其执行如下操作:

def create(conn, %{"user" => user_params}) do
changeset = User.changeset(%User{}, user_params)
case MyApp.Repo.insert changeset do
{:ok, changeset} ->
conn
|> put_flash(:info, "Your account was created")
|> redirect(to: "/")
{:error, changeset} ->
conn
|> put_flash(:info, "Unable to create account")
|> render("new.html", changeset: changeset)
end
end

现在你的 changeset.errors已丰富,您应该能够使用 changeset.errors[:email] 获取错误

关于elixir - 唯一索引约束在 Phoenix 应用程序中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32864685/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com