Как я могу добавить ограничение взаимного исключения с Ecto? - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть схема с двумя полями, 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

1 Ответ

0 голосов
/ 29 апреля 2018

Вы можете подсчитать количество присутствующих полей и проверить, равно ли оно 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
...