#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. Теперь я добавил основной контроллер корзины