我有一个user
,我想确保user
至少有first_name
或last_name
或nickname
。 user
不必包含所有字段。只要一个就足够了。默认代码仅为所有字段提供验证。如何重写它以检查OR而不是AND?
defmodule Vutuv.User do
use Vutuv.Web, :model
schema "users" do
field :first_name, :string
field :last_name, :string
field :nickname, :string
timestamps
end
@required_fields ~w(first_name last_name nickname)
@optional_fields ~w()
@doc """
Creates a changeset based on the `model` and `params`.
If no params are provided, an invalid changeset is returned
with no validation performed.
"""
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
答案 0 :(得分:2)
您必须先将所有字段从@required_fields
移至@optional_fields
:
@required_fields ~w()
@optional_fields ~w(first_name last_name nickname)
然后,在changeset/2
中使用自定义验证器:
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
|> validate_first_name_or_last_name_or_nickname(params)
end
def validate_first_name_or_last_name_or_nickname(changeset, :empty) do
changeset
end
def validate_first_name_or_last_name_or_nickname(changeset, _) do
first_name = get_field(changeset, :first_name)
last_name = get_field(changeset, :last_name)
nickname = get_field(changeset, :nickname)
if first_name || last_name || nickname do
# No error if any of those 3 are present.
changeset
else
# All the 3 fields are nil.
message = "first_name or last_name or nickname must be present"
changeset
|> add_error(:first_name, message)
|> add_error(:last_name, message)
|> add_error(:nickname, message)
end
end