Closed kevinkirkup closed 1 month ago
The valid?
flag is being propagated properly but the the errors
for the nested changesets are not.
Can you please provide a small snippet that reproduces the error? You can use Mix.install([:ecto])
and build your schemas there. Thank you.
I tried to reproduce the error without success using the script below.
Mix.install([
{:ecto, "~> 3.11.2"}
])
defmodule User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :name, :string
field :age, :integer
embeds_many :posts, Post
end
def changeset(model, params \\ %{}) do
model
|> cast(params, [:name, :age])
|> cast_embed(:posts, with: &Post.changeset/2)
|> validate_length(:name, min: 2)
|> validate_inclusion(:age, 18..100)
end
end
defmodule Post do
use Ecto.Schema
import Ecto.Changeset
schema "posts" do
field :title, :string
field :content, :string
belongs_to :user, User
embeds_many :comments, Comment
end
def changeset(model, params \\ %{}) do
model
|> cast(params, [:title, :content])
|> cast_embed(:comments, with: &Comment.changeset/2)
|> validate_required([:title, :content])
|> validate_length(:title, min: 2)
end
end
defmodule Comment do
use Ecto.Schema
import Ecto.Changeset
schema "comments" do
field :content, :string
belongs_to :post, Post
end
def changeset(model, params \\ %{}) do
model
|> cast(params, [:content])
|> validate_required([:content])
|> validate_length(:content, min: 2)
end
end
# Changeset with errors in all levels
changeset = User.changeset(%User{}, %{
name: "J",
age: 16,
posts: [
%{
title: "A",
content: "B",
comments: [
%{content: "C"},
%{content: "D"}
]
}
]
})
Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
=> %{
name: ["should be at least %{count} character(s)"],
age: ["is invalid"],
posts: [
%{
title: ["should be at least %{count} character(s)"],
comments: [
%{content: ["should be at least %{count} character(s)"]},
%{content: ["should be at least %{count} character(s)"]}
]
}
]
}
# Changeset with errors in the deepest level
changeset = User.changeset(%User{}, %{
name: "John",
age: 34,
posts: [
%{
title: "A very long title",
content: "Beautiful content",
comments: [
%{content: "Comment 1"},
%{content: nil}
]
}
]
})
Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
=> %{posts: [%{comments: [%{}, %{content: ["can't be blank"]}]}]}
Thank you, we can close this for now and reopen once we can reproduce it!
Just a heads up. This looks like it was related to an issue with the https://hexdocs.pm/polymorphic_embed module, not with Ecto itself.
Thanks for looking!
Elixir version
elixir 1.17.2-otp-27
Database and Version
Postgres 11
Ecto Versions
ecto_sql 3.11.2, ecto 3.11.2
Database Adapter and Versions (postgrex, myxql, etc)
Postgres 0.19.1
Current behavior
Expected behavior