【问题标题】:Ecto.Changeset not validatingEcto.Changeset 未验证
【发布时间】:2017-10-15 01:00:12
【问题描述】:

我正在试验 Ecto,但在验证 changeset() 函数中的数据时遇到问题。

Schema如下:

defmodule Barakuda.TestData do
  use Ecto.Schema

  schema "test_data" do
    field :username, :string
    field :age, :integer
  end

  def changeset(data, params \\ %{}) do
    data
    |> Ecto.Changeset.cast(params, [:username, :age])
    |> Ecto.Changeset.validate_required([:username, :age])
  end

end

现在让我们尝试无效数据:

iex(125)> d1=%Barakuda.TestData{id: 1, username: "polo"}
%Barakuda.TestData{__meta__: #Ecto.Schema.Metadata<:built, "test_data">,
 age: nil, id: 1, username: "polo"}
iex(126)> Barakuda.TestData.changeset(d1).valid?        
false

没关系,因为缺少 age 字段。如果我删除username,也会发生同样的情况。很好!

现在,我在changeset() 的末尾添加以下行(并且,是的,我重新编译了):

data
  |> Ecto.Changeset.cast(params, [:username, :age])
  |> Ecto.Changeset.validate_required([:username, :age])
  |> Ecto.Changeset.validate_number(:age, less_than: 20)

如果age 严格小于 20,这应该为真,例如:19、18、...,否则为假。正确的?让我们试一试:

iex(19)> d1=%Barakuda.TestData{id: 1, username: "polo", age: 15}
%Barakuda.TestData{__meta__: #Ecto.Schema.Metadata<:built, "test_data">,
 age: 15, id: 1, username: "polo"}
iex(20)> Barakuda.TestData.changeset(d1).valid?                 
true

没关系。然而

iex(130)> d1=%Barakuda.TestData{id: 1, username: "polo", age: 22}
%Barakuda.TestData{__meta__: #Ecto.Schema.Metadata<:built, "test_data">,
 age: 22, id: 1, username: "polo"}
iex(131)> Barakuda.TestData.changeset(d1).valid?                 
true

对于其他 validate_* 函数实际上也会发生同样的情况,例如(有或没有 count: :codepoints):

Ecto.Changeset.validate_length(:username, min: 6, count: :codepoints)

那么,我做错了什么?

注意:Elixir 1.5.1 和 Ecto v2.2.6 (2017-09-30)

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:

    validate_length 不检查现有字段,仅检查“更改”字段。

    validate_length(变更集、字段、选项)

    验证更改是给定长度的字符串或列表。

    Source

    由于您使用结构中的所有字段调用Barakuda.TestData.changeset,而params 参数中没有任何字段,因此没有字段被Ecto 标记为“已更改”,validate_length 什么也不做。正确的方法是将现有结构(具有默认/现有值)作为第一个参数传递,所有需要验证的添加作为第二个参数params。以下代码应为您返回false

    changeset = Barakuda.TestData.changeset(%Barakuda.TestData{}, %{id: 1, username: "polo", age: 22})
    changeset.valid?
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-08
      • 2018-01-18
      • 1970-01-01
      相关资源
      最近更新 更多