elixir - Unique index constraint not working in Phoenix app -
in phoenix app have user model follows:
defmodule myapp.user use myapp.web, :model schema "users" 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 changeset based on `model` , `params`. if no params provided, invalid changeset returned no validation performed. """ def changeset(model, params \\ :empty) model |> cast(params, @required_fields, @optional_fields) |> unique_constraint(:email) |> unique_constraint(:username) |> validate_format(:email, ~r/@/) |> validate_length(:password, min: 5) end end
i have following migration:
defmodule myapp.repo.migrations.createuser use ecto.migration def change create table(:users) add :email, :string add :username, :string add :crypted_password, :string timestamps end create unique_index(:users, [:email]) create unique_index(:users, [:username]) end end
and have registration_controller_ex
follows:
defmodule myapp.registrationcontroller use myapp.web, :controller alias myapp.user def new(conn, _params) changeset = user.changeset(%user{}) render conn, changeset: changeset end def create(conn, %{"user" => user_params}) changeset = user.changeset(%user{}, user_params) if changeset.valid? user = myapp.registration.create(changeset, myapp.repo) conn |> put_flash(:info, "your account created") |> redirect(to: "/") else conn |> put_flash(:info, "unable create account") |> render("new.html", changeset: changeset) end end end
so, i'm pretty sure username
, email
fields in user unique indexes. make sure unique calling unique_constraint
validate user.changeset. however, when in interface create user same email , username preivously created one, changeset validated , user "created". (it's not created, when database nothing added)
i following on server logs, changeset.valid? true.
[debug] begin [] ok query=139.3ms queue=8.2ms [debug] insert "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
also, other things in user.changeset function (such minimum password length , other things) reported user , working fine. it's unique indexes :email
, :username
failing reported.
the unique_constraint
checked database , triggered upon inserting record. calling changeset.valid?
not check constraints , in case return true. need check return tuple of repo insert , act on like:
def create(conn, %{"user" => user_params}) changeset = user.changeset(%user{}, user_params) case myapp.repo.insert changeset {:ok, changeset} -> conn |> put_flash(:info, "your account created") |> redirect(to: "/") {:error, changeset} -> conn |> put_flash(:info, "unable create account") |> render("new.html", changeset: changeset) end end
now changeset.errors
enriched , should able fetch error changeset.errors[:email]
Comments
Post a Comment