Rails Cart удаляет себя

#ruby-on-rails #ruby #ruby-on-rails-4 #cart

#ruby-on-rails #ruby #ruby-on-rails-4 #Корзина

Вопрос:

У меня проблема с моей корзиной в приложении электронной коммерции. Когда пользователь входит в систему и добавляет товар в корзину, товар добавляется не сразу. Пользователь должен вернуться и добавить его во второй раз, прежде чем он попадет в корзину.

Я просмотрел журналы и смог обнаружить, что проблема возникает, когда пользователь ранее что-то купил и подписывается на покупку позже.В следующий раз, когда они войдут в систему, чтобы купить другой товар, это произойдет, когда это произойдет.

Система пытается удалить старую корзину и создать новую, но в конечном итоге происходит то, что новая корзина отображается пустой с первой попытки.

Есть ли способ избежать этого?

Любая помощь будет оценена. Заранее спасибо!

 class Customer::CartsController < ApplicationController
  before_action :authenticate_user!
  def show
      if current_user
    if current_user.cart.purchased_at
        session[:cart_id] = nil
    else
    @cart = current_user.cart ||= Cart.find_by(session[:cart_id])
    end 
end
if session[:cart_id].nil?
    current_user.cart = Cart.create!(user_id: params[:id])
    session[:cart_id] = current_user.cart.id 
end
@cart = current_user.cart
end
  

Контроллер корзины создает действие

 class CartsController < ApplicationController
 def create
  @cart = Cart.new(cart_params)

  respond_to do |format|
  if @cart.save
    format.html { redirect_to @cart, notice: 'Cart was successfully created.' }
    format.json { render :show, status: :created, location: @cart }
  else
    format.html { render :new }
    format.json { render json: @cart.errors, status: :unprocessable_entity }
  end
end
end
  

Модель корзины

 class Cart < ActiveRecord::Base
has_many :line_items, dependent: :destroy
belongs_to :user

def add_product(product_id, size)
    current_item = line_items.find_by(product_id: product_id, size: size)
    if current_item
        current_item.quantity  = 1
    else
        current_item = line_items.build(product_id: product_id, size: size)
    end
    return current_item
end

def total_price
    line_items.to_a.sum { |item| item.total_price }
end

end
  

Пользовательская модель

 class User < ActiveRecord::Base
 devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :invitable,
has_one :cart
after_create :default_cart

def add_products_from_session cart_id
if role == customer?
  session_cart = Cart.find cart_id if cart_id
end
if cart amp;amp; session_cart
  session_cart.line_items.each{ |li| self.cart.line_items << li }
  session_cart.reload
  session_cart.destroy
elsif session_cart
  self.cart = session_cart
end

private
  def default_cart
   self.create_cart
  end
end
  

Код, добавляющий товар в корзину

Из контроллера позиций

   def create
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product.id, params[:size])

respond_to do |format|
  if @line_item.save
    format.html { redirect_to customer_cart_path }
    format.json { render :show, status: :created, location: @line_item }
  else
    format.html { render :new }
    format.json { render json: @line_item.errors, status: :unprocessable_entity }
  end
end
end
  

Комментарии:

1. Не могли бы вы также добавить свою корзину и пользовательские модели, пожалуйста?

2. @GrahamS. добавлено

3. Какое действие контроллера # вызывает неожиданное поведение? Вы случайно не написали для этого тест?

4. @eeeeeean Показать действие выше! Нет, я не написал тест

Ответ №1:

Cart.create!(user_id: params[:id]) выглядит странно. Я думаю, это должно быть Cart.create!(user_id: current_user.id) или current_user.create_cart . Кроме того, вам нужно немного изменить свой код. Я предлагаю:

 def show
  setup_cart
end



def create
  setup_cart
  # ... your code
end

protected

def setup_cart
  # user logged in
  if current_user
    # when cart purchased reset existing one
    if current_user.cart.purchased_at
       session[:cart_id] = nil
       current_user.cart = nil       
    end 

    # use existing one, marked in session or create a new one 
    @cart = current_user.cart || Cart.where(id: session[:cart_id]).first || current_user.create_cart
    @cart.user = current_user # in case first login
    @cart.save!
  else # no user logged in
    @cart = Cart.where(id: session[:cart_id]).first || Cart.create! 
  end

  session[:cart_id] = @cart.id
end
  

Комментарии:

1. Какую ошибку вы получаете? Возможно, другое действие изменяет session[:cart_id] или current_user.cart

2. Ошибки нет, но товар просто не попадает в корзину с первого раза. Возможно, я неправильно объяснил. Это действие запускается, когда вы нажимаете «добавить в корзину», поэтому он пытается очистить корзину и добавить товар одновременно, и, по сути, вы получаете пустую корзину с первой попытки.

3. Итак, вам нужно проверить действие, в котором вы вызываете add_product или add_products_from_session . show Действие больше не должно быть проблемой. Пожалуйста, добавьте код для вашего действия, при котором вы добавляете товар в корзину.

4. Ваш код не показывает, как @cart настроен на действие create . Вы можете извлечь код из show и использовать before_action или вызвать извлеченный метод из show и create . Я соответствующим образом изменю свой пример.

5. Теперь я добавил основной контроллер корзины