我有一个包含两个字段a
和b
的架构,我想要一个字段。也就是说,如果提供a
,b
不应该,反之亦然。
有没有办法通过Ecto变更集验证来优雅地表示这一点?像这样:
schema "foo" do
field(:a, :string)
field(:b, :string)
field(:c, :string)
timestamps()
end
def changeset(transaction, attrs) do
transaction
|> cast(attrs, [:a, :b, :c])
|> validate_required([:c])
|> validate_mutual_exclusion([:a, :b])
end
defp validate_mutual_exclusion(changeset, fields) do
# What goes here?
end
答案 0 :(得分:1)
您可以计算存在的字段数,并检查是否等于1:
defp validate_mutual_exclusion(changeset, fields) do
present = Enum.count(fields, fn field -> present?(get_field(changeset, field)) end)
case present do
1 -> changeset # ok
_ ->
# add an error to each field
Enum.reduce(fields, changeset, fn field, changeset ->
add_error(changeset, field, "exactly one of these must be present: #{inspect(fields)}")
end)
end
end
present?
只检查值是""
还是nil
:
def present?(nil), do: false
def present?(""), do: false
def present?(_), do: true