How to validate that at least 2 variable fields in a form are filled

How do I validate that at least 2 form fields have been filled? It doesn’t matter which ones, just as long as 2 out of n fields are filled.
I’ve gone through the answers here https://stackoverflow.com/questions/42212425/conditional-validation-in-ecto-for-or-1-of-2-fields-is-required, but I can’t seem to appropriate it to my needs.

one way would be to Enum.filter to return true for all the fields that are present? and then check that the length or count is larger than 2…

eg


Enum.filter(fields, &present?(changeset, &1)) |> length > 2

or 

Enum.filter(fields, &present?(changeset, &1)) |> Enum.count > 2

I would be very careful to call the validation with the specific fields |> validate_required_inclusion([:title , :content]) - say you add a checkbox in the future and you don’t want code to break or unexpected behaviour as that checkbox all of a sudden counts in this validation…

def validate_required_inclusion(changeset, fields) do
  if Enum.filter(fields, &present?(changeset, &1)) |> length > 2 do
    changeset
  else
    # Add the error to the first field only since Ecto requires a field name for each error.
    add_error(changeset, hd(fields), "Two of these fields must be present: #{inspect fields}")
  end
end

def present?(changeset, field) do
  value = get_field(changeset, field)
  value && value != ""
end
2 Likes

Thanks, this works great!