Rails:如何将购物车保存到用户会话?

时间:2016-03-25 20:06:08

标签: ruby-on-rails activerecord cart

在我的应用程序中,我设计了一个购物车,同时遵循与 Agile Web Development With Rails 4 一书中的布局类似的格式,我有一个小问题。因此,用户可以将商品添加到购物车,查看购物车,查看每件商品的价格以及总价。我遇到的问题是当用户将物品放入购物车然后退出时,即使不同的用户登录,购物车也会将物品保留在购物车中。我认为正确的方法是每个用户都有自己的个人大车。

这是我的用户模型和控制器

class User < ActiveRecord::Base
  has_one :cart 
  # :confirmable, :lockable, :timeoutable and :omniauthable
  # :confirmable, :lockable, :timeoutable and :omniauthable
  has_secure_password
  validates :email, presence: true
end

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def show
    @user = User.find(params[:id])
  end

  def create
    @user = User.new(user_params)
      if @user.save
        session[:user_id] = @user.id
        redirect_to @user
      else
        render 'new'
      end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
      if @user.update_attributes(user_params)
        redirect_to @user
      end
  end

  private
  def user_params
    params.require(:user).permit(:first_name, :admin, :last_name, :email, :password, :password_confirmation, :phone_number, :address_one, :address_two, :city, :country, :state, :zip)
    end
end

我的购物车型号和控制器

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

  def add_part(part_id)
    current_part = line_items.find_by(part_id: part_id)
    if current_part
      current_part.quantity += 1
    else
      current_part = line_items.build(part_id: part_id)
    end
    current_part
  end

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

class CartsController < ApplicationController
  before_action :set_cart, only: [:show, :edit, :update, :destroy]
  rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart

  def show
    @cart = Cart.find(params[:id])
  end

  def edit
    @cart = Cart.new(cart_params)
  end

  def update
    @cart = Cart.find(params[:id])
      if @cart.update_attributes(cart_params)
        redirect_to @cart
      end
  end

  def destroy
    @cart.destroy if @cart.id == session[:cart_id]
    session[:cart_id] = nil
    respond_to do |format|
      format.html { redirect_to root_path }
      format.json { head :no_content }
  end
end

  private
  def cart_params
    params.require(:cart).permit(:user_id)
    end

   def invalid_cart
     logger.error "Attempt to access invalid cart #{params[:id]}"
     redirect_to root_path, notice: "Invalid cart"
   end
end

和我的订单项控制器和当前模块(订单项将部件与我的布局中的购物车相关联)

class LineItemsController < ApplicationController
  include CurrentCart
  before_action :set_cart, only: [:create]
  before_action :set_line_item, only: [:show, :edit, :update, :destroy]


  def create
    part = Part.find(params[:part_id])
    @line_item = @cart.add_part(part.id)

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

module CurrentCart
  extend ActiveSupport::Concern

  private

      def set_cart
        @cart = Cart.find(session[:cart_id])
      rescue ActiveRecord::RecordNotFound
        @cart = Cart.create
        session[:cart_id] = @cart.id
      end
    end 

关于如何让一个购物车与一个用户联系的任何建议都将是一个很大的帮助:)如果需要更多的信息只是问。再次感谢!

1 个答案:

答案 0 :(得分:0)

哈哈哈!我做了整本书,从未意识到这个错误!

是的...所以会话的内容很可爱,但你可以通过这样的方式让它更安全:

def set_cart
    @cart = Cart.find_by(id: session[:cart_id], user: session[:user_id])
  rescue ActiveRecord::RecordNotFound
    @cart = Cart.create
    session[:cart_id] = @cart.id
  end

现在我知道你没有session[:user_id],但我猜你已经对如何完成它已经有了一个很好的想法。 ;)

提示:登录