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

vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
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
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
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

Other popular topics Top

hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 49134 226
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44167 214
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