I have a simple schema with a structure like this:
defmodule Parent do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field(:name, :string)
embeds_many(:children, Child)
end
def changeset(data, attrs) do
data
|> cast(attrs, [:name])
|> cast_embed(:children)
end
end
defmodule Child do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field(:key, :string)
field(:name, :string)
end
def changeset(data, attrs) do
data
|> cast(attrs, [:name, :key])
end
end
It works with data like this:
Parent.changeset(%Parent{}, %{
name: "Parent name",
children: [
%{name: "child name", key: "child_key"}
]
})
But I’d like to make it work with this:
Parent.changeset(%Parent{}, %{
name: "Parent name",
children: %{
child_key: %{name: "child name"}
}
})
This does not crash, but child_key
is lost in the conversion.
What is the best way to accept both format?
I could do something like:
def changeset(data, attrs) do
data
|> cast(prepare_attributes(attrs), [:name])
|> cast_embed(:children)
end
But this means the prepare_attributes
would need to do a lot of things that ecto does (accepting atom or string keys for attrs, handling missing keys…).