2017-10-14 3 views
0

J'expérimente Ecto et j'ai des problèmes avec la validation des données dans la fonction changeset().Ecto.Changeset non valide

Le Schema est la suivante:

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 

permet maintenant d'essayer avec des données non valides:

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 

C'est ok que le champ age manque. La même chose se passe si je supprime le username. Bien!

Maintenant, j'ajouter la ligne suivante à la fin de changeset() (et, oui, je recompiler):

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

Ceci est censé être vrai si age est strictement inférieur à 20, ei: 19, 18, ... et faux sinon. Droite? Essayons:

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 

ce qui est OK. Pourtant,

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 

La même chose se fait pour d'autres fonctions validate_* comme par exemple (avec ou sans count: :codepoints):

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

Alors, qu'est-ce que je fais mal?

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

Répondre

1

validate_length ne vérifie pas les champs existants, seulement "changé" champs.

validate_length (ChangeSet, champ, opte)

valide un changement est une chaîne ou une liste de la longueur donnée.

Source

Depuis que vous appelez Barakuda.TestData.changeset avec tous les champs de la struct et rien dans l'argument params, aucun champ est marqué comme « changé » par Ecto et validate_length ne fait rien. La façon correcte de le faire est de passer la structure existante (avec les valeurs par défaut/existantes) comme premier argument et tous les ajouts qui doivent être validés comme second argument, params. Le code suivant doit renvoyer false pour vous:

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