Reputation: 137
I created a cart where a user can increment and decrement an item's quantity. There's a problem when decrementing an item's quantity one by one. For example when I have "2x Pizza", where 2 is the quantity of the pizza, I decrement its quantity by one. So then I have "1x Pizza". When I again decrement the quantity, I get an error can't modify frozen Hash
.
My code:
def RemoveItemQuantity
@cart = current_cart
menu = Menu.find(params[:menu_id])
@line_item = @cart.sub_menu(menu.id)
if @line_item != nil
respond_to do |format|
if @line_item.save
# ...
end
end
end
end
def sub_menu(menu_id)
current_item = line_items.where(:menu_id => menu_id).first
if current_item
current_item.quantity -= 1
end
if current_item.quantity == 0
current_item.destroy
end
current_item
end
When the quantity of an item becomes 0
, I destroy the current_item
. After this it cannot save the record because of the can't modify frozen Hash
error. What am I doing wrong here?
Upvotes: 0
Views: 100
Reputation: 18672
The error happens because you're trying to save the destroyed record. I guess the easiest way to solve the problem is to make sure the saving and destroying happens in the same place.
You can refactor the code method a bit:
def remove_item_quantity
@cart = current_cart
menu = Menu.find(params[:menu_id])
@line_item = line_items.where(:menu_id => menu_id).first
if @line_item
respond_to do |format|
if @cart.sub_menu(@line_item)
# ...
end
end
end
end
def sub_menu(current_item)
if current_item.quantity > 1
current_item.update(quantity: current_item.quantity - 1)
else
current_item.destroy
end
end
Notice that I look up @line_item
in remove_item_quantity
. Since you're already checking if the item exists, I moved the call to sub_menu
inside the respond_to
block.
sub_menu
simply checks if the item has a quantity higher than 1
. If it does, it decrements by one and saves the record. If the quantity is 1
, it will become 0
when decrementing, so it's destroyed without updating the counter.
sub_menu
now always returns true
when either saving or destroying the record has succeeded.
Upvotes: 1
Reputation: 2435
I believe you can't do in-place mathematical assignment to ActiveRecord Objects. You need an appropriate update method.
Try changing:
current_item.quantity -= 1
To:
current_item.update_column( :quantity, current_item.quantity - 1 )
Upvotes: 0