如何添加条件必填字段?

时间:2015-11-25 17:31:39

标签: elixir phoenix-framework ecto

我有一个带有此(简化)架构的地址的ecto模型:

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而不是可选,但仅当国家/地区位于白名单中时,我才能找到一种干净的方式来编写验证。如何添加该约束?

2 个答案:

答案 0 :(得分: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。这是变更集的最大好处:它只是数据结构,您可以使用常规Elixir代码进行条件检查,验证等。直接写入,读取和测试。 :)

答案 1 :(得分:0)

要求cast之外的字段没有明确的功能。您可以使用validate_length/3功能并覆盖':message'选项。

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