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:
- You can have
jsonb[]columns with a default ofNULL embeds_onehas a default ofnil- 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
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
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
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
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.
Popular in Discussions
Other popular topics
Chat & Discussions>Discussions
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









