sodapopcan
I have a form with arbitrary levels of deeply nested associations. One particular association that lives a couple of levels down can have an upload associated with it. To track these I need to allow_upload based on the indices of each level. Currently this looks like this:
socket.assigns.form.source
|> Ecto.Changeset.get_assoc(:mockups)
|> Enum.with_index()
|> Enum.reduce(socket, fn {mockup, mockup_index}, socket ->
mockup
|> Ecto.Changeset.get_assoc(:elements)
|> Enum.with_index()
|> Enum.reduce(socket, fn {element, element_index}, socket ->
element
|> Ecto.Changeset.get_assoc(:transformations)
|> Enum.with_index()
|> Enum.reduce(socket, fn {_transformation, transformation_index}, socket ->
allow_image_upload(
socket,
"transformation-#{mockup_index}-#{element_index}-#{transformation_index}"
)
end)
end)
end)
I’m wondering how others would go about this.
Of course I realize I can abstract out the commonalities into a private function, but I would rather not do that as this is the only place this type of thing is happening and feel it’ll make it less readable for passers-by. I’m wondering if there is a reducer pattern that can do this type of nested thing in a flat pipeline. I have a feeling Pathex can probably come in handy here but interested in other options. I’m thinking of reducing into a 2-tuple of {socket, %{}} and building up the indices in the map then doing a final reduction to build up all the keys and allow_upload them, but that feels like it will be more complex to read.
Anyway, just wondering! As verbose as my example is, I don’t hate it as it’s pretty easy to read. Credo is complaining about the indentation depth, though, and I don’t necessarily disagree with it.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex










Marked As Solved- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
100phlecs
It’s a great tool, one of the main reasons I like Elixir.
Yes, if you need to update the socket, then you can tack on
reduce:Also Liked
100phlecs
When you start dealing with nested iterative structures,
foris your best bet.LostKobrakai
It also supports
reduce, to allow wiring the socket state through.sodapopcan
Beautiful! So much nicer than what I was thinking.
Thank you both!
Last Post!
Sorc96
Personally, I probably wouldn’t bother looking into
assoc_with_index, the usage makes pretty clear what it does. I’m also not saying that I would necessarily rewrite the code like this, I just wanted to show that thereducewas causing the most complexity here, in my opinion.I guess my issue with the original code is that you need to thread the
socketthrough all the layers in order to use it in the innermostreduce. That complicates it a lot for me, because the creation of the names and modification of the socket are mixed together. So maybe a version with a fewflat_maps that generate the values first and then areduce- basically myforexample, but without thefor -would be a pretty good solution as well.