danschultzer

danschultzer

Pow Core Team

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.

Showing Posts 1 to 2

tangui

tangui

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> with field.value
  • building a collaborative editing system relying on changesets (stored in DB)

image

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:

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!

danschultzer

danschultzer OP

Pow Core Team

I think the typo is actually from Ecto API change, I’m updating it thanks!

Yeah, I did look at the library but it doesn’t really solve polymorphic embeds with Ecto and neither does my small version here. The actual production version I have is more involved so it can handle some normalization, prepare changes, etc. But at the end of the day, embeds have some sharp corners and it only gets worse when you lose the guarantee with the struct which Ecto is built upon. There are a lot of assumptions with data structures in Ecto so I think the only way for polymorphic embeds to work properly is that Ecto needs to be changed in how embeds works. It’s been a while so I can’t remember the exact details, but if you go through the code path of how embeds are dumped/loaded you’ll see that embeds are treated separately from other data and it makes things tricky.

At least having all of this logic in your codebase you can adjust it for your exact needs and work around the sharp corners yourself. You often don’t need everything that the embed type need to be able to do.

— All posts loaded —

Where Next? Top

Trending in Blog Posts Top

bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
pckrishnadas88
Hey everyone! :waving_hand: I’ve published Part 7 of the Building Distributed Systems in Elixir series, where we build core distributed ...
New
zorn
An educational side project in Elixir, Phoenix, and Tauri. I share what I learned while wiring Automerge into the BEAM, including how I s...
New
nathanl
Process labels are useful for visualization and debugging. Here’s why you should use them.
New
abreujp
New article: Elixir Project Structure — From mix new to a Growing Codebase I’ve published a new article in my Elixir learning series on d...
New
andreasronge
What happens if you design tools for LLMs instead of letting LLM use human tools ? Wrote a blog on why and what that enables. As I see ...
New
mudasobwa
Somewhere, right now, a senior engineer is on the verge of a nervous breakdown because his company will not let him switch from Claude to...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews