Reputation: 3760
Ecto 3.2.5, Phoenix 1.4.11, Elixir 1.9.4
I have an Ecto Changeset that looks something like this. I have numerous fields that I would like to run validate_length
on all with the same max length.
my_model
|> validate_required(required_fields())
|> validate_length(:field, max: 255)
|> validate_length(:another_field, max: 255)
# More of the same validate_length
Instead of listing one-by-one I also tried something along these lines of this with my Changeset after the piping above, without luck.
Enum.map([:field, :another_field], fn string_field ->
Ecto.Changeset.validate_length(ch, string_field, max: 255)
end)
validate_length
only takes a single field by default, so how can I validate length on multiple fields without a line-by-line validate_length
?
Upvotes: 2
Views: 1364
Reputation: 121010
Enum.map/2
would not work because what you actually are to perform would be to reduce changeset on many fields via validation.
Simply declare the normal private function like the below
@spec validate_length_many(
changeset :: Ecto.Changeset.t(), fields :: [atom()]
) :: Ecto.Changeset.t()
defp validate_length_many(
%Ecto.Changeset{} = changeset, fields
) when is_list(fields) do
Enum.reduce(fields, changeset, fn field, changeset ->
validate_length(changeset, field, max: 255)
end)
end
and use it as
my_model
|> validate_required(required_fields())
|> validate_length_many(~w[f1 f2]a)
or call Enum.reduce/3
directly (it won’t pipe well because the first argument in the call to Enum.reduce/3
would be a list of fields).
changeset = validate_required(my_model, required_fields())
Enum.reduce([:f1, :f2], changeset, fn field, changeset ->
validate_length(changeset, field, max: 255)
end) #⇒ changeset
Upvotes: 1