Getting errors out of nested embedded schemas

When using an embedded schema that contains an embeds_one, what is the best way to gather all the errors? Is there a way to gather all the errors for both Foo and Bar at once, or do I need to do it manually by going through my changeset’s changes like this:

changeset = Foo.changeset(%Foo{}, %{bar: %{}})
changeset.changes[:bar].errors

Here’s some sample code:

defmodule Foo do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key false
  embedded_schema do
    field :foo, :string
    embeds_one :bar, Bar do
      field :required_field, :string
    end
  end

  def changeset(%Foo{} = foo, attrs) do
    foo
    |> cast(attrs, [:foo])
    |> cast_embed(:bar, with: &bar_changeset/2, required: true)
  end

  def bar_changeset(schema, attrs) do
    schema
    |> cast(attrs, [:required_field])
    |> validate_required([:required_field])
  end
end

changeset = Foo.changeset(%Foo{}, %{bar: %{}})
IO.puts changeset.changes[:bar].er
1 Like

Can something like this work?

errors = (for change <- changeset.changes, do: change.errors) |> List.flatten

It looks like I’ll need something more like this:

errors = (for change <- changeset.changes, do: elem(change, 1).errors) |> List.flatten

The change itself looks like this:

iex(10)> errors = (for change <- changeset.changes, do: change)
[bar: #Ecto.Changeset<action: :insert, changes: %{},  errors: [required_field: {"can't be blank", [validation: :required]}],  data: #Foo.Bar<>, valid?: false>]

I was hoping for something a little cleaner, but I can make this work.

Thanks.

Checked out Ecto.Changeset.traverse_errors/2 yet?

5 Likes

Perfect, that’s more what I was looking for. Thanks!

1 Like