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