Slowboy Slowboy - 2 months ago 6
Ruby Question

Can't add Products back to Products model after deleting it from Cart, Ruby on rails

In an E commerce Rails App I'm building products that is deleted from the ShoppingCart are not added back to the production model after deletion.

When I add Products to the Cart the App is using this controller below to decrease the number of products from the Product model( see the create method)

controllers/product_item_controller.rb


class ProductItemsController < ApplicationController

include CurrentCart

before_action :set_cart, only: [:create]
before_action :set_product_item, only: [:show, :destroy]

def create

@product = Product.find(params[:product_id])
@product_item = @cart.add_product(@product.id)
if @product_item.save
redirect_to root_url, notice:'Product added to Cart'
product = Product.find params[:product_id]
product.update_columns(stock_quantity: product.stock_quantity - 1)
else
render :new
end
end

private

def set_product_item
@product_item = ProductItem.find(params[:id])
end

def product_item_params
params.require(:product_item).permit(:product_id)
end

end


That is woking fine.

But when I delete the Cart it gets deleted but the products are not added to the products model. And I also get this messages :
Invalid Cart


this is the
carts_controller.rb


class CartsController < ApplicationController

before_action :set_cart, only: [:show, :destroy]
rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart

def new
@cart = Cart.new
end

def show
@images = ["1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg"]
@random_no = rand(5)
@random_image = @images[@random_no]

end


def destroy
@cart.destroy if @cart.id == session[:cart_id]
session[:cart_id] = nil
product = Product.find params[:product_id]
product.update_columns(stock_quantity: product.stock_quantity + 1)
redirect_to root_url, notice: 'Your Cart is Empty'
end

def remove
cart = session['cart']
item = cart['items'].find { |item| item['product_id'] == params[:id] }

product = Product.find(item['product_id'])
product.update_columns(stock_quantity: product.stock_quantity + 1)

if item
cart['items'].delete item
end
redirect_to cart_path
end


private

def set_cart
@cart = Cart.find(params[:id])
end

def cart_params
params[:cart]
end

def invalid_cart
logger_error = 'You are trying to access invalid cart'
redirect_to root_url, notice: 'Invalid Cart'
end
end


I Can't see what is wrong with this code and why the products are not added to the
product.rb
after being deleted from the Cart.

Am I missing something here? Could someone advise me here?

Below are other relevant models and controllers

products_controller.rb


class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]


def show

end

def search

@product = Product.search(params[:query]).order("created_at DESC")
@categories = Category.joins(:products).where(:products => {:id => @product.map{|x| x.id }}).distinct

end

private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end

# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :description, :price_usd, :price_isl, :image, :category_id, :stock_quantity, :label_id, :query)
end
end


Cart.rb
model

class Cart < ActiveRecord::Base

has_many :product_items, dependent: :destroy

def add_product(product_id)
current_item = product_items.find_by(product_id: product_id)
if current_item
current_item.quantity += 1

else
current_item = product_items.build(product_id: product_id)
end
current_item


end

def total_price_usd
product_items.to_a.sum{|item| item.total_price_usd}
end

def total_price_isl
product_items.to_a.sum{|item| item.total_price_isl}
end
end


product.rb
model

Class Product < ActiveRecord::Base
belongs_to :category
belongs_to :label

has_many :product_item, :dependent => :destroy

#before_destroy :ensure_not_product_item



validates :title, :description, presence: true
validates :price_usd, :price_isl, numericality: {greater_than_or_equal_to: 0.01}
validates :title, uniqueness: true


has_attached_file :image, styles: { medium: "500x500#", thumb: "100x100#" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/

#def ensure_not_product_item
# if product_item.empty?
# return true
# else
# errors.add(:base, 'You have Product Items')
# return false
# end

#end

def self.search(query)

where("title LIKE ? OR description LIKE ?", "%#{query}%", "%#{query}%")
end
end

Answer

You are rescuing from ActiveRecord::RecordNotFound

rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart

But you're probably rescuing inappropriately... from the Product.find... in the destroy method. I'm not sure why you would expect the product_id to be in params.

Your code...

def destroy
    @cart.destroy if @cart.id == session[:cart_id]
    session[:cart_id] = nil
    product = Product.find params[:product_id]
    product.update_columns(stock_quantity: product.stock_quantity + 1)
    redirect_to root_url, notice: 'Your Cart is Empty'
end

A better alternative might be...

def destroy
    if @card.id == session[:cart_id]
      @cart.product_items each do |product_item|
        product_item.product.update_columns(stock_quantity: product_item.product.stock_quantity + 1)
      end
      @cart.destroy
    end
end

However this might better be done as a before_destroy action for product_item model, so that destroying a product_item will automatically increment the stock total.

Comments