Search code examples
ruby-on-railsrubye-commerceshopping-cart

Updating in stock quantity based on shopping cart quantity in rails app?


I'm working on a E Commerce app and I can´t figure out how I can update the product stock quantity when the user adds product to the cart. I followed a tutorial for most of this app since I'm a total newbie. But the tutorial doesn't go into how to update the product stock quantity when the user adds product to the cart.

so far I've added this method to the cart.rbmodel

 def upd_quantity
  if cart.purchased_at
   product.decrement!(quantity: params[:stock_quantity])
  end
 end

But I´m really stuck and don't know what I'm doing It would be great if someone could take a look at this and advise me how to implement this function to the app.

here is a link to the github repo https://github.com/DadiHall/brainstore

this what I have at the moment.

cart_item.rb model

class CartItem
attr_reader :product_id, :quantity

  def initialize product_id, quantity = 1
    @product_id = product_id
    @quantity = quantity
  end

  def increment
    @quantity = @quantity + 1
  end

  def product
    Product.find product_id
  end

  def total_price
    product.price * quantity
  end

  def upd_quantity
   if cart.purchased_at
   product.decrement!(quantity: params[:stock_quantity])
  end
 end

end

cart.rbmodel

class Cart
    attr_reader :items

    def self.build_from_hash hash
        items = if hash ["cart"] then 
            hash["cart"] ["items"].map do |item_data|
        CartItem.new item_data["product_id"], item_data["quantity"]
        end

    else
        []
    end

        new items
    end


  def initialize items = []
    @items = items
  end

  def add_item product_id
    item = @items.find { |item| item.product_id == product_id }
    if item
      item.increment
    else
      @items << CartItem.new(product_id)
    end
  end

  def empty?
    @items.empty?
  end

  def count
    @items.length
  end

  def serialize 
    items = @items.map do |item| 
        {
            "product_id" => item.product_id, 
            "quantity" => item.quantity
        }
    end

    {

            "items" => items
    }


  end

  def total_price
    @items.inject(0) { |sum, item| sum + item.total_price }
  end
end

product.rb model

    class Product < ActiveRecord::Base

        mount_uploader :image, ImageUploader

        validates_presence_of :name, :price, :stock_quantity
        validates_numericality_of :price, :stock_quantity

        belongs_to :designer
        belongs_to :category
        belongs_to :page

        def self.search(query)

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


`cart_controller.rb`

class CartsController < ApplicationController
    before_filter :initialize_cart

    def add
        @cart.add_item params[:id]
        session["cart"] = @cart.serialize
        product = Product.find params[:id]
        redirect_to :back, notice: "Added #{product.name} to cart."
    end

    def show

    end

    def checkout
        @order_form = OrderForm.new user: User.new
        @client_token = Braintree::ClientToken.generate
    end

    def remove
  cart = session['cart']
  item = cart['items'].find { |item| item['product_id'] == params[:id] }
  if item
    cart['items'].delete item
  end
   redirect_to cart_path
  end


end

Solution

  • Does adding this line: product.update_columns(stock_quantity: product.stock_quantity - 1)

    To your add action in the CartsController do the trick?

    def add
        @cart.add_item params[:id]
        session["cart"] = @cart.serialize
        product = Product.find params[:id]
    
        product.update_columns(stock_quantity: product.quantity - 1)
    
        redirect_to :back, notice: "Added #{product.name} to cart."
    end
    

    Try this for removing the product from cart:

        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
    

    Note, this will only work if you are adding and removing 1 item/product at a time. I suggest renaming 'item' to 'product' in your remove action for consistency.