I’m not sure why I got:
** (ArgumentError) cast/3 expects a list of atom keys, got: `"name"`
(ecto 3.3.3) lib/ecto/changeset.ex:560: Ecto.Changeset.cast_key/1
(ecto 3.3.3) lib/ecto/changeset.ex:518: Ecto.Changeset.process_param/7
(elixir 1.10.2) lib/enum.ex:2111: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto 3.3.3) lib/ecto/changeset.ex:504: Ecto.Changeset.cast/6
priv/repo/seeds.exs:21: anonymous fn/2 in :elixir_compiler_2.__FILE__/1
priv/repo/seeds.exs:47: (file)
for the following code:
alias Pxblog.Repo
alias Pxblog.Role
alias Pxblog.User
import Ecto.Query, only: [from: 2]
find_or_create_role = fn role_name, admin ->
case Repo.all(from(r in Role, where: r.name == ^role_name and r.admin == ^admin)) do
[] ->
%Role{}
|> Role.changeset(%{name: role_name, admin: admin})
|> Repo.insert!()
_ ->
IO.puts("Role: #{role_name} already exists, skipping")
end
end
find_or_create_user = fn username, email, role ->
case Repo.all(from(u in User, where: u.username == ^username and u.email == ^email)) do
[] ->
%User{}
|> User.changeset(%{
username: username,
email: email,
password: "test",
password_confirmation: "test",
role_id: role.id
})
|> Repo.insert!()
_ ->
IO.puts("User: #{username} already exists, skipping")
end
end
_user_role = find_or_create_role.("User Role", false)
admin_role = find_or_create_role.("Admin Role", true)
_admin_user = find_or_create_user.("admin", "admin@test.com", admin_role)
I’m on:
Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]
Elixir 1.10.2 (compiled with Erlang/OTP 21)
and
{:ecto_sql, "~> 3.3"},
{:jason, "~> 1.0"},
{:myxql, "~> 0.3.0"}
defmodule Pxblog.Role do
use Ecto.Schema
import Ecto.Changeset
schema "roles" do
field(:name, :string)
field(:admin, :boolean, default: false)
has_many(:users, Pxblog.User)
timestamps(type: :utc_datetime)
end
@required_fields ~w(name admin)
@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 \\ :invalid) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
defmodule Pxblog.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field(:username, :string)
field(:email, :string)
field(:password_digest, :string)
belongs_to(:role, Pxblog.Role)
has_many(:posts, Pxblog.Post)
timestamps(type: :utc_datetime)
# Virtual Fields
field(:password, :string, virtual: true)
field(:password_confirmation, :string, virtual: true)
end
@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 \\ %{}) do
model
|> cast(params, [:username, :email, :password, :password_confirmation, :role_id])
|> hash_password
|> validate_required([:username, :email, :password, :password_confirmation, :role_id])
|> validate_confirmation(:password, message: "does not match password!")
|> unique_constraint(:username)
|> unique_constraint(:email)
|> validate_length(:password, min: 4)
end
defp hash_password(changeset) do
if password = get_change(changeset, :password) do
changeset
|> put_change(:password_digest, Comeonin.Bcrypt.hashpwsalt(password))
else
changeset
end
end
end