Rails Cart Returns the number of items on Destroy
I am new to rails and have a simple grocery store website. When a user adds a product to their cart or updates the number of rows in the cart, they add / remove from the base quantity of the product as needed. However, when they empty their cart (delete / destroy the cart), it does not restore the amount of the base product, as if they were not buying anything. How do I update the destroy method to return the rows listed below to the original product quantity?
line_items_controller.rb - An example of a method to completely remove one line_item product in the cart and increase the amount of the base product:
def empty
product = Product.find(params[:product_id])
@line_item = @cart.empty_product(product)
@total = @line_item.quantity
product.increment!(:quantity, @total)
respond_to do |format|
if @line_item.save
format.html { redirect_to :back, notice: 'Product removed.' }
format.js
format.json { render :show, status: :ok, location: @line_item }
else
format.html { render :edit }
format.json { render json: @line_item.errors, status: :unprocessable_entity }
end
end
end
carts / show.html.erb - Call to destroy / empty the cart:
<%= link_to 'Empty Cart', @cart, method: :delete, data: {confirm: 'Are you sure you want to empty your cart?'}, :class => 'btn btn-danger whiteText' %>
carts_controller.rb - Current carts destruction method:
def destroy
@cart.destroy if @cart.id == session[:cart_id]
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to root_path, notice: 'Cart was emptied.' }
format.json { head :no_content }
end
end
carts_controller.rb - What I'm trying to do (I think there might be a problem with this as it doesn't know how to resolve product = Product.find (params [: product_id])):
def destroy
@cart.destroy if @cart.id == session[:cart_id]
@cart.line_items.each do
product = Product.find(params[:product_id])
@total = @line_item.quantity
product.increment!(:quantity, @total)
end
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to root_path, notice: 'Cart was emptied.' }
format.json { head :no_content }
end
end
EDIT
Tried changing the destroy method:
def destroy
if @cart.id == session[:cart_id]
@cart.line_items.each do |l|
product = Product.where(:id => l.product_id)
@total = @l.quantity
product.increment!(:quantity, @total)
end
@cart.destroy
end
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to root_path, notice: 'Cart was emptied.' }
format.json { head :no_content }
end
end
This gives me the following error, although I was able to use an increment! by product quantity in line_control_name:
undefined method `increment!' for #<Product::ActiveRecord_Relation:0xb5ad1b4>
Also tried calling the path directly into the carts controller method. It shows the cart is empty successfully, but does not return the product quantity depending on how it looks when I call this same method in html:
if @cart.id == session[:cart_id]
@cart.line_items.each do |l|
empty_line_item_path(product_id: l.product)
end
@cart.destroy
end
source to share
For the destruction question, you can actually do it at the model level.
In your LineItem model, you can do ...
before_destroy { |record| record.product.increment!(:quantity, record.quantity }
This assumes the LineItem has ...
belongs_to :product
And will ensure the product quantity is updated regardless of where the line_item entry was destroyed.
source to share
For your error after your EDIT part, you have ...
product = Product.where(:id => l.product_id)
@total = @l.quantity
product.increment!(:quantity, @total)
The method where
does not return a single product, it returns a production relation (which probably only contains one product).
It would be better ...
product = Product.find_by(:id => l.product_id)
@total = @l.quantity
product.increment!(:quantity, @total)
... which will return a product object.
source to share