2015-11-25 25 views
9

Ben bu (basitleştirilmiş) şema ile bir adres için bir ecto modeli vardır:Koşullu bir zorunlu alan nasıl eklenir?

Ben ülke beyaz listede olduğunu, ancak eğer sadece yapamam ama yerine opsiyonel gerekli şekilde zip işaretlemek istediğiniz
defmodule Address do 
    use Ecto.Model 

    schema "addresses" do 
    field :zip, :string 
    field :country, :string 
    # snip 
    end 

    @countries_requiring_zip ~w(US) # snip 

    def changeset(model, params \\ :empty) do 
    model 
    |> cast(params, ~w(country), ~w(zip)) 
    |> validate_zip 
    end 

    defp validate_zip(changeset) do 
    if get_field(changeset, :country) in @countries_requiring_zip do 
     # ???? 
    end 

    changeset 
    end 
end 

Doğrulamayı yazmanın temiz bir yolunu bulmak. Bu kısıtlamayı nasıl ekleyebilirim?

cevap

11

Sadece birden tanımlayabilir çok atmalarını:

def changeset(model, params \\ :empty) do 
    model 
    |> cast(params, ~w(country), ~w()) 
    |> cast_by_country(params) 
end 

defp cast_by_country(changeset, params) do 
    case get_field(changeset, :country) do 
    "US" -> cast(changeset, params, ~w(zip), ~w()) 
    _ -> cast(changeset, params, ~w(), ~w(zip)) 
    end 
end 

get_field/2 değişikliklerden bir değerini okumak ve bir yoksa yapı tek çare olacaktır. Bu, değişikliklerin en büyük yararıdır: sadece veri yapısıdır ve koşullu kontroller, doğrulamalar vb. Yapmak için normal Elixir kodunu kullanabilirsiniz. Yazmak, okumak ve test etmek için düz ileri. :)

0

cast dışında bir alan gerektirmesi için açık bir işlev yoktur. validate_length/3 işlevini kullanabilir ve ': message' seçeneğini geçersiz kılabilirsiniz.

validate_length(changeset, :zip, min: 1, message: "is required when country is US") 
İlgili konular