benonymus

benonymus

Enum.reduce refactor with multi

Hey there,

I have this function:

  defp add_same_price(order, ids) do
    filtered_order_book = get_incomplete_orders(ids, order.command)

    same_price_orders =
      filtered_order_book
      |> Enum.filter(fn x -> Decimal.cmp(x.price, order.price) == :eq and x.id != order.id end)

    summed_order =
      Enum.reduce(same_price_orders, order, fn x, acc ->
        amount_sum = Decimal.add(x.amount, acc.amount)

        LimitOrder.changeset_update_amount_completed(x, %{completed: true, amount: x.amount})
        |> Repo.update()

        Map.put(acc, :amount, amount_sum)
      end)

    LimitOrder.changeset_update_amount_completed(order, %{
      completed: summed_order.completed,
      amount: summed_order.amount
    })
    |> Repo.update()
  end

This works well, but I think that doing the transaction inside the reduce is not great, because this way if the last transaction fails the previous ones wont be rolled back.
How can I refactor this using multi?
Usually when I use multi that is my acc, but i need the result of this reduce function as well.
I think that if i would just have the multi as my acc here too, i’d need to update the order, that happens as the last thing currently, inside the reduce as well, and then get(how?) it from the multi. Is this in the good direction? Thoughts?

Marked As Solved

LostKobrakai

LostKobrakai

If you need results of previous steps consider Ecto.Multi.run and Ecto.Multi.merge. Those should give you options to do what you need to do.

Edit: Maybe I’ve misunderstood the question a bit. Your reduce function can hold any value, so it can hold a multi struct and the summed amouns:

Enum.reduce(orders, %{order: order, multi: multi}, fn x, %{order: order, multi: multi} -> 
  # To stuff
  %{order: order, multi: multi}
end)

Also Liked

LostKobrakai

LostKobrakai

  %{order: summed_order, multi: multi} =
    Enum.reduce(same_price_orders, %{order: order, multi: Multi.new()}, fn x, acc ->
      amount_sum = Decimal.add(x.amount, acc.order.amount)

      changeset =
        LimitOrder.changeset_update_amount_completed(x, %{
          completed: true,
          amount: x.amount
        })

      %{
        order: Map.put(acc.order, :amount, amount_sum),
        multi: Multi.update(acc.multi, x.id, changeset)
      }
    end)

Last Post!

LostKobrakai

LostKobrakai

  %{order: summed_order, multi: multi} =
    Enum.reduce(same_price_orders, %{order: order, multi: Multi.new()}, fn x, acc ->
      amount_sum = Decimal.add(x.amount, acc.order.amount)

      changeset =
        LimitOrder.changeset_update_amount_completed(x, %{
          completed: true,
          amount: x.amount
        })

      %{
        order: Map.put(acc.order, :amount, amount_sum),
        multi: Multi.update(acc.multi, x.id, changeset)
      }
    end)

Where Next?

Popular in Questions Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement