Ecto.Changeset没有验证

时间:2017-10-14 16:12:29

标签: elixir ecto

我正在尝试使用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,e.i: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)

那么,我做错了什么?

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

1 个答案:

答案 0 :(得分:2)

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

  

validate_length(变更集,字段,操作)

     

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

Source

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

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