Ecto 验证失败且没有错误
Ecto validation fails with no error
我正在尝试创建一个基本的 CRUD 应用程序,但我遇到了验证问题。这是我的控制器操作:
def update(conn, %{"id" => id, "user" => params}) do
case Repo.get(User, String.to_integer(id)) do
user when is_map(user) ->
user = Map.merge(user, atomize_keys(params))
case User.validate(user) do
[] ->
Repo.update(user)
redirect conn, to: user_path(:show, user.id)
errors ->
text conn, "Validation Failed!"
##render conn, "editform.html", user: user, errors: errors
end
_ ->
redirect conn, to: user_path(:index)
end
end
和我的模特:
defmodule MyApp.User do
use Ecto.Model
validate user,
email: present()
schema "users" do
field :first_name, :string
field :last_name, :string
field :email, :string
field :created_at, :datetime, default: Ecto.DateTime.local
field :updated_at, :datetime, default: Ecto.DateTime.local
end
end
User.validate(user) 似乎返回了一些东西,但不是错误 - form.html 中没有显示错误。我在这里错过了什么?这可能是 atomize_keys() 函数的问题吗?这是那个:
defp atomize_keys(struct) do
Enum.reduce struct, %{}, fn({k, v}, map)
-> Map.put(map, String.to_atom(k), v) end
end
你的配置应该是这样的:
# config/config.exs
use Mix.Config
# Your endpoint config and your logger config go here...
# DB config:
config :my_app, MyApp.Repo,
adapter: Ecto.Adapters.Postgres,
database: "myapp",
username: "username",
password: "password",
server: "localhost"
那么你的模型可以是这样的:
defmodule MyApp.User do
use Ecto.Model
schema "users" do
field :first_name, :string
field :last_name, :string
field :email, :string
field :created_at, :datetime, default: Ecto.DateTime.local
field :updated_at, :datetime, default: Ecto.DateTime.local
end
def changeset(params, :create) do
# Read the docs for Ecto.Changeset.cast, by including email in the second argument, it becomes required, the third argument are the optional arguments. Anything not in these two lists will be dropped out of the passed in params.
# User validate_change for other custom validations.
%User{}
|> cast(params, ~w(email), ~(first_name last_name)
|> validate_unique(:email, on: MyApp.Repo)
end
def changeset(params, :update, user) do
user
|> cast(params, [], ~w(email first_name last_name))
|> validate_unique(:email, on: MyApp.Repo)
end
end
此模型代码的精彩部分意味着您的控制器可以如下所示:
def update(conn, %{"id" => id, "user" => params}) do
user = MyApp.Repo.get(User, id)
case user do
%MyApp.User{} ->
changeset = User.changeset(params, :update, user)
if changeset.valid? do
Repo.update(changeset)
redirect conn, to: user_path(:show, user.id)
else
render conn "editform.html", user: user, errors: changeset.errors
end
_ ->
redirect conn, to: user_path(:index)
end
end
我正在尝试创建一个基本的 CRUD 应用程序,但我遇到了验证问题。这是我的控制器操作:
def update(conn, %{"id" => id, "user" => params}) do
case Repo.get(User, String.to_integer(id)) do
user when is_map(user) ->
user = Map.merge(user, atomize_keys(params))
case User.validate(user) do
[] ->
Repo.update(user)
redirect conn, to: user_path(:show, user.id)
errors ->
text conn, "Validation Failed!"
##render conn, "editform.html", user: user, errors: errors
end
_ ->
redirect conn, to: user_path(:index)
end
end
和我的模特:
defmodule MyApp.User do
use Ecto.Model
validate user,
email: present()
schema "users" do
field :first_name, :string
field :last_name, :string
field :email, :string
field :created_at, :datetime, default: Ecto.DateTime.local
field :updated_at, :datetime, default: Ecto.DateTime.local
end
end
User.validate(user) 似乎返回了一些东西,但不是错误 - form.html 中没有显示错误。我在这里错过了什么?这可能是 atomize_keys() 函数的问题吗?这是那个:
defp atomize_keys(struct) do
Enum.reduce struct, %{}, fn({k, v}, map)
-> Map.put(map, String.to_atom(k), v) end
end
你的配置应该是这样的:
# config/config.exs
use Mix.Config
# Your endpoint config and your logger config go here...
# DB config:
config :my_app, MyApp.Repo,
adapter: Ecto.Adapters.Postgres,
database: "myapp",
username: "username",
password: "password",
server: "localhost"
那么你的模型可以是这样的:
defmodule MyApp.User do
use Ecto.Model
schema "users" do
field :first_name, :string
field :last_name, :string
field :email, :string
field :created_at, :datetime, default: Ecto.DateTime.local
field :updated_at, :datetime, default: Ecto.DateTime.local
end
def changeset(params, :create) do
# Read the docs for Ecto.Changeset.cast, by including email in the second argument, it becomes required, the third argument are the optional arguments. Anything not in these two lists will be dropped out of the passed in params.
# User validate_change for other custom validations.
%User{}
|> cast(params, ~w(email), ~(first_name last_name)
|> validate_unique(:email, on: MyApp.Repo)
end
def changeset(params, :update, user) do
user
|> cast(params, [], ~w(email first_name last_name))
|> validate_unique(:email, on: MyApp.Repo)
end
end
此模型代码的精彩部分意味着您的控制器可以如下所示:
def update(conn, %{"id" => id, "user" => params}) do
user = MyApp.Repo.get(User, id)
case user do
%MyApp.User{} ->
changeset = User.changeset(params, :update, user)
if changeset.valid? do
Repo.update(changeset)
redirect conn, to: user_path(:show, user.id)
else
render conn "editform.html", user: user, errors: changeset.errors
end
_ ->
redirect conn, to: user_path(:index)
end
end