Auto Updating values in embedded schemas

def add_to_cart(%Order{line_item: []} = cart, cart_params) do
    attrs = %{line_item: [cart_params]}
    update_cart(cart, attrs)
  end
  def add_to_cart(%Order{line_item: existing_line_item} = cart, cart_params) do
    existing_line_item = existing_line_item |> Enum.map(&Map.from_struct/1)
    attrs = %{line_item: [cart_params | existing_line_item]}
    update_cart(cart, attrs)
  end

This function adds items to a line_item embedded schema which works as a cart at the frontend. I want to make it increase the quantity of an item if the item already exists in the cart, cause it keeps adding items to the list even if it already exist in the list. need some help here.

1 Like

I think in the second clause of add_to_cart you need to do an Enum.find on existing_line_item (should it be existing_line_items? a little confusing naming) to see if the list already includes whatever id you’re adding via cart_params?

@bglusman I would appreciate it if you could show me how that could be done in this case

Well, i can try but would need more context/details into the context and schemas/structs involved… as an example, if cart_params == %{line_item_id: 5}, and existing_line_item == [%{line_item_id: 5, quantity: 1}, %{line_item_id: 6, quantity: 1}] then

  def add_to_cart(%Order{line_item: existing_line_item} = cart, cart_params) do
    added_item_id = cart_params.line_item_id
    existing_line_item = existing_line_item |> Enum.map(&Map.from_struct/1)
    updated_cart_params =
       case Enum.find_index(existing_line_item, & &1.line_item_id == added_item_id) do
           nil -> [cart_params | existing_line_item]
           index ->
              current_item = Enum.at(existing_line_item, index)
              updated_item = %{current_item | quantity: current_item.quantity + 1}
              List.replace_at(existing_line_item, index, updated_item)
       end
    attrs = %{line_item: updated_cart_params}
    update_cart(cart, attrs)
  end

I didn’t test that and it might be easier to structure things differently, but if I’ve gotten current structure approximately right and you want only local changes, I think approximately that should work.

1 Like

Edited it to this:

def add_to_cart(%Order{line_item: existing_line_item} = cart, cart_params) do
    added_item_id = cart_params.item_id
    existing_line_item = existing_line_item |> Enum.map(&Map.from_struct/1)

    updated_cart_params =
      case Enum.find_index(existing_line_item, &(&1.item_id == added_item_id)) do
        nil ->
          [cart_params | existing_line_item]

        index ->
          current_item = Enum.at(existing_line_item, index)
          updated_item = %{current_item | quantity: current_item.quantity + 1}
          List.replace_at(existing_line_item, index, updated_item)
      end

    attrs = %{line_item: updated_cart_params}
    update_cart(cart, attrs)
  end

but i am still geting the same result.

Sorry, I’m not sure if I can help anymore without more information, it may be helpful to play around in an IEx console to debug/understand whats happening and verify the steps you think are happening… do you understand what my code above is doing that’s different from your initial code, and why that seems like it would fix your issue to me?

1 Like