Применение Ecto validate_length для нескольких полей в Changeset - PullRequest
0 голосов
/ 27 января 2020

Ecto 3.2.5, Phoenix 1.4.11, Elixir 1.9.4

У меня есть набор изменений Ecto, который выглядит примерно так. У меня есть множество полей, которые я хотел бы запустить validate_length на всех с одинаковой максимальной длиной.

my_model
|> validate_required(required_fields())
|> validate_length(:field, max: 255)
|> validate_length(:another_field, max: 255)
# More of the same validate_length

Вместо того, чтобы перечислять по одному, я также попробовал кое-что в этом направлении с моей Changeset после описанного выше безуспешно.

Enum.map([:field, :another_field], fn string_field ->
  Ecto.Changeset.validate_length(ch, string_field, max: 255)
end)

validate_length по умолчанию принимает только одно поле, так как я могу проверить длину для нескольких полей без построчной validate_length?

1 Ответ

1 голос
/ 27 января 2020

Enum.map/2 не будет работать, потому что на самом деле вы должны будете уменьшить набор изменений во многих полях посредством проверки.

Просто объявите обычный приватный используйте функцию, подобную приведенной ниже

@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

и используйте ее как

my_model
|> validate_required(required_fields())
|> validate_length_many(~w[f1 f2]a)

или вызовите Enum.reduce/3 напрямую (она не будет транслироваться хорошо, поскольку первый аргумент в вызов Enum.reduce/3 будет список полей).

changeset = validate_required(my_model, required_fields())
Enum.reduce([:f1, :f2], changeset, fn field, changeset ->
  validate_length(changeset, field, max: 255)
end) #⇒ changeset
...