如何让session[:cart_size]在用户重新登录后保持持久化?
问题描述
应用中购物车商品数量(cart_size)在用户同一会话内可正常保持,但用户购物车有商品时登出再登录后,购物车图标显示为空,订单视图却仍能看到商品。需要实现cart_size在用户登出再登录后持久化显示。
现有代码
OrderItemsController
class OrderItemsController < ApplicationController before_action :authenticate_user! def create order_item = current_order.order_items.new(article_id: params[:article_id]) if order_item.save session[:cart_size] = current_order.order_items.size redirect_to root_path, notice: 'Successfully added to cart.' else redirect_to root_path, alert: 'Error adding to cart.' end end def destroy order_item = OrderItem.find(params[:id]) order_item.destroy session[:cart_size] = current_order.order_items.size redirect_to order_item_path, notice: 'Successfully removed from cart.' end def current_order order = Order.where(user_id: current_user.id, status: 'created').order(updated_at: :desc).last order || Order.create(user_id: current_user.id) end end
购物车图标调用
<%= session[:cart_size] || 0 %>
订单视图(views/orders/show.html.erb)
<% if @order&.order_items.present? %> <% @order.order_items.each do |order_item| %> <div><%=order_item.article.title%></div> <% else %> <span>You have no items in your cart</span> <% end %>
解决方案
问题根源是session[:cart_size]仅存储在当前会话中,用户登出后会话销毁,重新登录时新会话无该值。正确做法是从用户的当前订单实时获取商品数量,而非依赖session。
1. 移除session存储逻辑
修改OrderItemsController,删除所有设置session[:cart_size]的代码:
class OrderItemsController < ApplicationController before_action :authenticate_user! def create order_item = current_order.order_items.new(article_id: params[:article_id]) if order_item.save redirect_to root_path, notice: 'Successfully added to cart.' else redirect_to root_path, alert: 'Error adding to cart.' end end def destroy order_item = OrderItem.find(params[:id]) order_item.destroy redirect_to order_item_path, notice: 'Successfully removed from cart.' end def current_order order = Order.where(user_id: current_user.id, status: 'created').order(updated_at: :desc).last order || Order.create(user_id: current_user.id) end end
2. 视图中实时计算购物车数量
修改购物车图标代码,直接从当前用户的订单获取数量:
<% if user_signed_in? %> <%= current_order.order_items.size %> <% else %> 0 <% end %>
3. (可选)添加全局辅助方法
若多个页面需显示购物车数量,在ApplicationHelper中添加辅助方法:
module ApplicationHelper def cart_size return 0 unless user_signed_in? current_order.order_items.size end end
视图中直接调用:
<%= cart_size %>
4. 全局化current_order方法
将current_order移至ApplicationController并设为辅助方法,确保所有控制器和视图都能调用:
class ApplicationController < ActionController::Base before_action :authenticate_user!, except: [:index, :show] # 按需调整 def current_order return nil unless user_signed_in? order = Order.where(user_id: current_user.id, status: 'created').order(updated_at: :desc).last order || Order.create(user_id: current_user.id) end helper_method :current_order # 允许视图调用该方法 end
修改后,购物车数量将从数据库中用户的实时订单数据获取,无论登录状态如何变化,都能保持数据一致且持久化。
内容的提问来源于stack exchange,提问作者AndresM
相关产品推荐
相关产品推荐

