When I put an embeds_one
inside an embeds_one then cast_embed
fails:
iex(n)> MyApp.DeeplyNested.run
#Ecto.Changeset<
action: nil,
changes: %{
child: #Ecto.Changeset<
action: :insert,
changes: %{child_name: "child"},
errors: [],
data: #MyApp.DeeplyNested.Child<>,
valid?: true
>,
parent_name: "parent"
},
errors: [],
data: #MyApp.DeeplyNested<>,
valid?: true
>
** (ArgumentError) cannot cast embed `grant_child`, assoc `grant_child` not found. Make sure it is spelled correctly and properly pluralized (or singularized)
(ecto) lib/ecto/changeset.ex:841: Ecto.Changeset.relation!/4
(ecto) lib/ecto/changeset.ex:759: Ecto.Changeset.cast_relation/4
defmodule MyApp.DeeplyNested do
use Ecto.Schema
import Ecto.Changeset
alias __MODULE__
@primary_key false
embedded_schema do
field :parent_name, :string
embeds_one :child, Child, primary_key: false do
field :child_name, :string
embeds_one :grant_child, GrantChild, primary_key: false do
field :grant_child_name, :string
end
end
end
def changeset(%DeeplyNested{} = struct, %{} = params) do
ok_result = struct
|> cast(params, [:parent_name])
|> cast_embed(:child, required: true, with: &child_changeset/2)
|> IO.inspect
# this will fail...
ok_result
|> cast_embed(:grant_child, required: true, with: &grant_child_changeset/2)
end
defp child_changeset(struct, params) do
struct
|> cast(params, [:child_name])
|> validate_required([:child_name])
end
defp grant_child_changeset(struct, params) do
struct
|> cast(params, [:grant_child_name])
|> validate_required([:grant_child_name])
end
def run do
params = %{
parent_name: "parent",
child: %{
child_name: "child",
grant_child: %{
grant_child_name: "grant_child"
}
}
}
changeset(__struct__(), params)
end
end
Is this a known limitation? Does someone maybe have a workaround?