2015-11-25 22 views
9

私はこの(簡体字)スキーマを持つアドレスのエクトモデルがありますが、国がホワイトリストにあるが、私ができない場合にのみ、私は必要に応じて、代わりにオプションのzipをマークしたい条件付き必須フィールドを追加する方法は?

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 

を検証を書くためのきれいな方法を見つけ出してください。その制約をどのように追加するのですか?

答えて

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は変更から値を読み込み、1がない場合は、構造体1にフォールバックします。これはチェンジセットの最大の利点です。データ構造にすぎず、通常のElixirコードを使用して条件チェックや検証などを行うことができます。ストレートフォワード、書き込み、読み取り、テスト。 :)

0

cast以外のフィールドを必要とする明示的な機能はありません。 validate_length/3関数を使用し、 ':message'オプションを無効にすることができます。

validate_length(changeset, :zip, min: 1, message: "is required when country is US") 
関連する問題