Ecto.Changeset 未验证
Ecto.Changeset not validating
我正在试验 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)
所以,我做错了什么?
注意:Elixir 1.5.1 和 Ecto v2.2.6 (2017-09-30)
validate_length
不检查现有字段,只检查“已更改”的字段。
validate_length(changeset, field, opts)
Validates a change is a string or list of the given length.
由于您使用结构中的所有字段调用 Barakuda.TestData.changeset
而 params
参数中没有任何内容,因此没有字段被 Ecto 标记为“已更改”并且 validate_length
不执行任何操作.执行此操作的正确方法是将现有结构(具有 default/existing 值)作为第一个参数传递,并将所有需要验证的添加作为第二个参数传递,params
。下面的代码应该 return false
适合你:
changeset = Barakuda.TestData.changeset(%Barakuda.TestData{}, %{id: 1, username: "polo", age: 22})
changeset.valid?
我正在试验 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)
所以,我做错了什么?
注意:Elixir 1.5.1 和 Ecto v2.2.6 (2017-09-30)
validate_length
不检查现有字段,只检查“已更改”的字段。
validate_length(changeset, field, opts)
Validates a change is a string or list of the given length.
由于您使用结构中的所有字段调用 Barakuda.TestData.changeset
而 params
参数中没有任何内容,因此没有字段被 Ecto 标记为“已更改”并且 validate_length
不执行任何操作.执行此操作的正确方法是将现有结构(具有 default/existing 值)作为第一个参数传递,并将所有需要验证的添加作为第二个参数传递,params
。下面的代码应该 return false
适合你:
changeset = Barakuda.TestData.changeset(%Barakuda.TestData{}, %{id: 1, username: "polo", age: 22})
changeset.valid?