【问题标题】:How to add a conditional required field?如何添加条件必填字段?
【发布时间】:2015-11-25 17:31:38
【问题描述】:

我有一个带有这个(简化)架构的地址的 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 标记为必需而不是可选,但前提是该国家/地区在白名单中,但我想不出一种干净的方式来编写验证。如何添加该约束?

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    您也可以简单地定义多个演员表:

    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 代码进行条件检查、验证等。直接编写、阅读和测试。 :)

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        • 1970-01-01
        • 2017-06-17
        • 2012-10-14
        • 2019-03-15
        • 2021-08-27
        相关资源
        最近更新 更多