首页 > 解决方案 > 如何在嵌套变更集上使用 add_error?

问题描述

根据我在add_error 文档中的理解,它只能应用于顶级变更集。

我如何在嵌套的变更集上使用 add_error 呢?

例如,采用以下模式:

defmodule MyApp.Person do
  use Ecto.Schema
  import Ecto.Changeset

  schema "people" do
    field :first_name, :string
    field :last_name, :string
    field :other_field_made_to_fail, :string

    has_many :addresses, MyApp.Address
  end

  def changeset(person, attrs) do
    person
    |> cast(attrs, [:first_name, :last_name, :other_field_made_to_fail])
    |> validate_required([:first_name, :last_name])
  end
end

defmodule MyApp.Address do
  use Ecto.Schema
  import Ecto.Changeset

  schema "addresses" do
    field :street_name, :string
    field :city, :string
    field :state, :string

    belongs_to :person, MyApp.Person
  end

  def changeset(address, attrs) do
    address
    |> cast(attrs, [:street_name, :city, :state])
    |> validate_required([:city, :state])
    |> cast_assoc(:person, with: &MyApp.Person.changeset/2, required: true)
  end
end

并获取此数据输入:

%{
  "address" => %{
    "city" => "Test City",
    "state" => "Test State",
    "person" => %{
      "first_name" => "John",
      "last_name" => "Doe"
    }
  }
}

而由此产生的变更集:

#Ecto.Changeset<
  changes: %{
    address: #Ecto.Changeset<
      changes: %{
        city: "Test City",
        state: "Test State"
        person: #Ecto.Changeset<
          changes: %{
            first_name: "John",
            last_name: "Doe"
          }
        >
      },
      errors: []
      valid?: true
    >
  }
>

我将如何使用add_error/4将错误添加到:other_field_made_to_fail嵌套:person属性内部并保持其余变更集完好无损?

标签: elixirecto

解决方案


我设法弄清楚了。如果还有其他人感兴趣,解决方案是在您的变更集上调用update_change/3并调用一个函数作为代表嵌套变更集的第三个参数:

Ecto.Changeset.update_change(changeset, :person, fn person_changeset ->
  Ecto.Changeset.add_error(person_changeset, :other_field_made_to_fail, "error message here")
end)

最终结果是一个更新Address的变更集,现在包含Person带有错误的变更集。

您还可以使用update_change/3在嵌套变更集中执行其他变更集功能,它将返回更新的嵌套变更集。


推荐阅读