krainboltgreene

krainboltgreene

Why does `embeds_many` enforce a default of `[]`?

Today I noticed that when defining a embeds_many the new struct has a default of [] which is confusing since:

  1. You can have jsonb[] columns with a default of NULL
  2. embeds_one has a default of nil
  3. You can’t define your own default!

I ask because I have code that expected it to behave like other fields and also because {} in postgres is twice as expensive as an null value in postgres:

ecto/lib/ecto/schema.ex at master · elixir-ecto/ecto · GitHub.

Looks like it was committed 7 years ago: Remove containers in favor of strategies · elixir-ecto/ecto@7f052d9 · GitHub

First Post!

cmo

cmo

Don’t see how this makes the default for embeds many confusing. What else could this value be? And a list of nothing is an empty list, no?

I get what you mean that it could say there is no value here, but that is if you think of the embed many field as the value. I think of the values as the things being embedded.

Using a list over nil probably saves us from nil checks all over the place. Would you prefer to check if it’s nil before you try to operate on it every time?

Most Liked

josevalim

josevalim

Creator of Elixir

This is it. :slight_smile:

krstfk

krstfk

I would argue this is the only correct default. Embeds many represents associated records of which there can be 0 or more.
The number of records in NULL would be undefined, which would be incorrect.

LostKobrakai

LostKobrakai

Embeds are modeled to align closely with assocs and for assocs empty set doesn‘t mean there‘s a column somewhere set to NULL, but it means there‘s no rows at all. It makes sense to default that field to empty list, because as mentioned before it‘s much cleaner not to check for nil and empty list everywhere.

Last Post!

Yegair

Yegair

I can understand the reasoning, but I just had a case where being able to set an embeds_many to nil would have saved me a lot of trouble.

I have an existing schema/table with a field :foo, {:array, :string}. This field contains encoded values (I know, not the best design, but thats just how the database was designed quiet some time ago). I need to migrate to a new embeds_many :foo_new, MyCustomStruct. The table is rather large, so I can’t migrate all of the data at once and instead have to keep both columns running simultaneously for a while, i.e. the migration happens in the background.

Now in an API endpoint, I have to decide which of the two fields is the one, that I have to read the data from and send it to the client. Initially I wanted to allow nil for the :foo_new embed, so I could use it as a marker that tells me whether the record has already been migrated from :foo to :foo_new. This would have worked well, because [] is a valid value and I can’t use it to decide whether the data has been migrated. To be more specific, the code could have ignored the old :foo field and just write the :foo_new field, so as soon as there is a value in there, I’d have known, that the migration logic did run and :foo_new is the new source of truth.

It even works in production, because the database allows NULL values and Ecto returns them as nil for the embeds_many. However, things start to get problematic as soon as I write tests, because then I have to write a lot of workarounds to get the nil values into the test database, effectively rendering ExMachina etc. useless, because the thousands of existing tests now insert foo: [...], foo_new: [] and I can’t opt out of that behavior.

Where Next?

Popular in Discussions Top

lorenzo
Hey everone! I created a prototype for my app using Nodejs for the api. But the framework I chose wasnt great (in general theresnt any g...
New
opsb
We’re considering our architecture from a viewpoint of scaling our traffic heavily over the next 6 months. Our current deployment is runn...
New
Rustixir
Hi everyone, im working on find best language/framework/system for high concurrency, high performance and stable performance after wor...
New
fireproofsocks
I’ve been working on an Elixir project that has required a lot of scripting. I usually reach for Elixir because I like it more (and in th...
New
matthias_toepp
I’d love to hear what people think about Wisp, the new Gleam web framework started by Gleam’s primary creator Louis Pilfold. Gleam, alon...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
arcanemachine
https://nitter.net/josevalim/status/1744395345872683471 https://twitter.com/josevalim/status/1744395345872683471
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31586 112
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement