Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir 唯一索引约束在Phoenix应用程序中不起作用_Elixir_Phoenix Framework - Fatal编程技术网

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

Elixir 唯一索引约束在Phoenix应用程序中不起作用,elixir,phoenix-framework,Elixir,Phoenix Framework,在我的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, virtu

在我的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.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
我还有以下迁移:

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
我的
注册\控制器\u ex
如下:

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.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
因此,尽管如此,我非常确定用户中的
用户名
电子邮件
字段是唯一的索引。我还通过调用
unique\u 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
的唯一索引。

数据库将检查
唯一约束
,因此只有在插入记录时才会触发。调用
changeset.valid?
不会检查约束,因此在本例中返回true。您需要检查Repo insert的返回元组,并执行如下操作:

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]

获取错误,但它不起作用。我有一个问题:注册\控制器。例如:15:函数更改集/0未定义对于后代,上面的行应该稍微更改:changset=User.changeset(%User{},User\ params)