Recently I had to ensure semi-arbitrary data for an embedded schema could be validated and easily mapped in Phoenix forms. I didn’t need to store this data in the database. After tinkering with it for a bit polymorphic embeds was the solution.
Hi Dan,
Can’t thank you enough for this great write-up!
It became very useful as I was doing some funny things with [polymorphic_embed]( polymorphic_embed | Hex ), such as:
- highlighting changed form fields by comparing
field.form.data.<fieldname>withfield.value - building a collaborative editing system relying on changesets (stored in DB)

In both case, this was impossible with polymorphic_embed because it defines a new Ecto type that does not fully behave like regular embeds (and cannot, because of limitations in Ecto), hence numerous bug reports on this library such as [this one]( Dan Schultzer: Polymorphic embeds in Ecto ).
But you cracked it with this trick:
# We must modify the type so Ecto will handle this field as an embed.
changeset = %{changeset | types: Map.put(changeset.types, name, {:embed, relation})}
Now, may I ask if you took a look at polymorphic_embed before writing this blog post, and if so why you didn’t use it in the first place?
I’m curious because, if as I suppose correctly and the author of polymorphic_embed didn’t know about le trick, then I guess it could be rewritten by deleting 80% of the code and eliminating 80% of the bugs ![]()
Thinking out loud, but this library became unmaintained (it seems), is widely used and is riddled with subtle discrepancies compared with regular Ecto embeds. For those who would need it, a PR with “some” fixes here.
PS : might be a typo here:
+ {:parameterized, {__MODULE__, relation}} = Map.fetch!(types, name)
- {:parameterized, __MODULE__, relation} = Map.fetch!(types, name)
Cheers!






















