2017-10-14 91 views
0

我正在嘗試使用Ecto,並且在驗證changeset()函數中的數據時遇到了問題。Ecto.Changeset not validating

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是真實的,EI:19, 18,...否則返回false。對?讓我們試試看:

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) 

那麼,我究竟做錯了什麼?

注意:青春1.5.1和外生V2.2.6(2017年9月30日)

回答

1

validate_length不檢查現有油田中,只有 「變」 領域。

validate_length(變更,字段,選擇採用)

驗證的變化是給定長度的串或列表。

Source

既然你打電話Barakuda.TestData.changeset與在params論點的結構並沒有什麼所有的領域,如由外生「改變」和validate_length什麼也不做任何字段被標記。這樣做的正確方法是將現有結構(使用默認/現有值)作爲第一個參數,並將所有需要驗證的添加作爲第二個參數params。以下代碼應爲您返回false

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