2015-11-25 3 views
9

У меня есть модель экто для адреса с этим (упрощенной) схеме:Как добавить условное обязательное поле?

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 

Хочу отметить zip по мере необходимости, а не по желанию, но только тогда, когда страна находится в белом списке, но я не могу выяснить чистый способ написания проверки. Как добавить это ограничение?

ответ

11

Вы можете просто определить многократные проливает также:

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 прочтет значение от изменений и Откат к одной структуры, если не один. Это самое большое преимущество наборов изменений: это просто структура данных, и вы можете использовать обычный код Elixir для выполнения условных проверок, валидаций и т. Д. Прямо вперед, чтобы писать, читать и тестировать. :)

0

Не требуется явное функционирование поля за пределами cast. Вы можете использовать функцию validate_length/3 и переопределить параметр «: сообщение».

validate_length(changeset, :zip, min: 1, message: "is required when country is US") 
Смежные вопросы