Home > Blockchain >  Ruby Shopping cart cant save user
Ruby Shopping cart cant save user

Time:07-08

I am working on creating shop cart / order. I created shop cart with association by this guide so I have some problem. After a new sign in session My app can't find my previous cart and create one new

module ApplicationHelper

   def current_cart
    if !session[:cart_id].nil?
      Cart.find(session[:cart_id])
    else
      Cart.new
    end
  end
end
Cart_items_controller

class CartItemsController < ApplicationController
  def create
    @cart = current_cart
    @cart_item = @cart.cart_items.new(cart_params)
    @cart.save
    redirect_back fallback_location: root_path
    flash[:success] = "Items added to your cart"
    session[:cart_id] = @cart.id 
    
  end 

  def destroy
    @cart = current_cart
    @cart_item = @cart.cart_items.find(params[:id])
    @cart_item.destroy
    @cart_items = current_cart.cart_items
    redirect_to carts_path
  end

  private 
  
  def cart_params
    params.require(:cart_item).permit(:product_id, :user_id)
  end
end
Cart Controller

class CartsController < ApplicationController

  def index
  end

  def show
    @cart_items = current_cart.cart_items
    @order_item = current_order.order_items.new
  end

  def new
  end
end

My module association

class CartItem < ApplicationRecord
  belongs_to :cart
  belongs_to :product
end

class Cart < ApplicationRecord
  has_many :cart_items
end

class User < ApplicationRecord
  has_one :cart
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

class Product < ApplicationRecord
  has_one_attached :image
  has_many :order_items
  has_many :cart_items
end
Product controller show 
  def show
    @product = Product.find(params[:id])
    @cart_item = current_cart.cart_items.new
  end

Product view show 

...
  <%= form_for @cart_item, remote: true  do |f|%>
      <%= f.hidden_field :product_id, :value => @product.id %>
      <%= f.hidden_field :user_id, :value => current_user.id %>
      <%= f.submit "Add to Card ", class: "btn btn-primary"%>
  <% end %>

So my Schema

create_table "cart_items", charset: "utf8mb3", force: :cascade do |t|
    t.integer "cart_id"
    t.integer "product_id"
    t.integer "user_id"
  end

  create_table "carts", charset: "utf8mb3", force: :cascade do |t|
    t.integer "user_id"
  end

 create_table "products", charset: "utf8mb3", force: :cascade do |t|
    t.string "title"
    t.string "description"
    t.integer "price"
  end

create_table "users", charset: "utf8mb3", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "name"
  end

So what I get after adding to cart. enter image description here

I think problem with finding session[:cart_id] It return nil and after every sign in it create a new cart Can anyone help me?

CodePudding user response:

Your current_cart helper is creating a new cart any time there isn't one in the session. In a new session, there of course won't be a cart, even if the user has had one previously, so if you want to use their latest cart instead of always creating a new one, you could do something like this:

def current_cart
  if session[:cart_id].present?
    Cart.find(session[:cart_id])
  else
    current_user.cart || current_user.build_cart
  end
end

You should probably also make sure that a cart can't be created without an associated user, or you might end up with orphaned carts / cart items in your database, like in the screenshot you posted. The cart should have a belongs_to :user association, and user_id could be a foreign key with null: false on the database layer if you wanted to be extra safe. In your User model, the relation to cart could be has_one :cart, dependent: :destroy to make sure that the user's cart is destroyed when the user gets destroyed.

Also, it seems redundant to have a user_id in your cart_items table, since the user will of course be the same as in the associated cart. A has_one :user, through: :cart association should take care of that.

  • Related