I am following along with Phoenix 1.4 book, and I got to "Using the Repository Data" section when I tried to put in data into through the terminal to the database I got an error.
My IEx session:
iex(1)> alias Rumbl.Repo
Rumbl.Repo
iex(2)> alias Rumbl.Accounts.User
Rumbl.Accounts.User
iex(3)> Repo.insert(%User{
...(3)> name: "José", username: "josevalim"
...(3)> })
[debug] QUERY ERROR db=16.7ms queue=1.2ms
INSERT INTO "users" ("name","username","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["José", "josevalim", ~N[2018-11-24 11:47:30], ~N[2018-11-24 11:47:30]]
It threw the following error:
** (Ecto.ConstraintError) constraint error when attempting to insert struct:
* users_username_index (unique_constraint)
If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `unique_constraint/3` on your changeset with the constraint
`:name` as an option.
The changeset has not defined any constraint.
(ecto) lib/ecto/repo/schema.ex:641: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3
(elixir) lib/enum.ex:1314: Enum."-map/2-lists^map/1-0-"/2
(ecto) lib/ecto/repo/schema.ex:626: Ecto.Repo.Schema.constraints_to_errors/3
(ecto) lib/ecto/repo/schema.ex:238: anonymous fn/15 in Ecto.Repo.Schema.do_insert/3
It seems that you have created a unique index in your users
table migration.
The constraint is on your username
key meaning two records in the users
table cannot have the same username. In your case, that means you have already created another user in the table with the username josevalim
.
To get Ecto to return {:error, changeset}
tuple instead of raising an error, you can tell the schema that there's a unique constraint in your changeset/2
method:
def changeset(user, params) do
user
|> cast(params, [:name, :username])
|> validate_required([:name, :username])
|> unique_constraint(:username, name: :users_username_index)
end
And use this method to build a changeset before inserting anything:
%User{}
|> changeset(%{name: "José", username: "josevalim"})
|> Repo.insert