我有一个我一直在研究的phoenix / phx v1.3项目,并且在尝试使用iex
会话创建用户时遇到了问题。据我所知,我编写的代码应该正常工作,因为应用程序可以编译。
我运行了以下生成器来为用户帐户设置schema
。
mix phx.gen.json Accounts User users email:string encrypted_password:string username:string
然后,我接着介绍了几个关于如何设置架构以通过修改来接受创建用户帐户的教程,
/lib/kegcopr_api/accounts/user.ex
user.ex
defmodule KegCopRAPI.Accounts.User do
use Ecto.Schema
# import Ecto
import Ecto.Changeset
# import Ecto.Query
schema "accounts_users" do
field :email, :string
field :encrypted_password, :string
field :username, :string
field :password, :string, virtual: true
timestamps()
end
@required_fields ~w(email username)
@optional_fields ~w()
def changeset(struct, params \\ :empty) do
struct
|> cast(params, @required_fields, @optional_fields)
|> validate_required(@required_fields, @optional_fields)
# |> cast(params, [:email, :encrypted_password, :username])
# |> validate_required([:email, :encrypted_password, :username])
|> validate_format(:email, ~r/@/)
|> validate_length(:username, min: 1, max: 20)
|> update_change(:email, &String.downcase/1)
|> unique_constraint(:email)
|> update_change(:username, &String.downcase/1)
|> unique_constraint(:username)
end
def registration_changeset(struct, params) do
struct
|> changeset(params)
|> cast(params, ~w(password), [])
|> validate_required(~w(password), [])
|> validate_length(:password, min: 6, max: 100) |> put_encrypted_pw
end
defp put_encrypted_pw(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{password: pass}} -> put_change(changeset, :encrypted_password, Comeonin.Bcrypt.hashpwsalt(pass))
_ ->
changeset
end
end
end
然后我运行iex -S mix
为应用启动交互式elixir会话,我尝试使用以下命令将用户插入数据库,
changeset = KegCopRAPI.Accounts.User.registration_changeset(%KegCopRAPI.Accounts.User{}, %{email: "first@example.com", username: "first", password: "password"})
但是,上面提到的命令给出了以下错误,
warning: `Ecto.Changeset.cast/4` is deprecated, please use `cast/3` + `validate_required/3` instead
(kegcopr_api) lib/kegcopr_api/accounts/user.ex:21: KegCopRAPI.Accounts.User.changeset/2
(kegcopr_api) lib/kegcopr_api/accounts/user.ex:35: KegCopRAPI.Accounts.User.registration_changeset/2
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(stdlib) erl_eval.erl:438: :erl_eval.expr/5
(elixir) src/elixir.erl:224: :elixir.erl_eval/3
(elixir) src/elixir.erl:212: :elixir.eval_forms/4
(iex) lib/iex/evaluator.ex:182: IEx.Evaluator.handle_eval/6
(iex) lib/iex/evaluator.ex:175: IEx.Evaluator.do_eval/4
(iex) lib/iex/evaluator.ex:155: IEx.Evaluator.eval/4
(iex) lib/iex/evaluator.ex:61: IEx.Evaluator.loop/3
(iex) lib/iex/evaluator.ex:21: IEx.Evaluator.init/4
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
** (ArgumentError) unknown field "email" for changeset on %KegCopRAPI.Accounts.User{__meta__: #Ecto.Schema.Metadata<:built, "accounts_users">, email: nil, encrypted_password: nil, id: nil, inserted_at: nil, password: nil, updated_at: nil, username: nil}
(ecto) lib/ecto/changeset.ex:1318: Ecto.Changeset.ensure_field_exists!/2
(ecto) lib/ecto/changeset.ex:1305: anonymous fn/5 in Ecto.Changeset.validate_required/3
(elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto) lib/ecto/changeset.ex:1304: Ecto.Changeset.validate_required/3
(kegcopr_api) lib/kegcopr_api/accounts/user.ex:22: KegCopRAPI.Accounts.User.changeset/2
(kegcopr_api) lib/kegcopr_api/accounts/user.ex:35: KegCopRAPI.Accounts.User.registration_changeset/2
任何有关如何创建用户的帮助都将非常感激。目前,我不确定错误是在我输入的iex changeset命令中还是在user.ex
文件中。
答案 0 :(得分:3)
您正在将字符串列表传递给validate_required
,但它必须是原子列表。 cast
也可以。因此,将您的所有~w(...)
更改为~w(...)a
,它应该有效。我还会删除已弃用的API。
@required_fields ~w(email username)a
@all_fields ~w()a ++ @required_fields
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @all_fields)
|> validate_required(@required_fields)
# |> cast(params, [:email, :encrypted_password, :username])
# |> validate_required([:email, :encrypted_password, :username])
|> validate_format(:email, ~r/@/)
|> validate_length(:username, min: 1, max: 20)
|> update_change(:email, &String.downcase/1)
|> unique_constraint(:email)
|> update_change(:username, &String.downcase/1)
|> unique_constraint(:username)
end
def registration_changeset(struct, params) do
struct
|> changeset(params)
|> cast(params, ~w(password))
|> validate_required(~w(password)a)
|> validate_length(:password, min: 6, max: 100)
|> put_encrypted_pw
end