在购物的同时有两个对象

时间:2014-05-07 06:59:38

标签: ruby-on-rails

同时有两个物品没有一个添加到我的购物车中。这是controllermodels

class PublicController < ApplicationController
    before_filter :find_or_create_cart, :only => [:add_to_cart, :show_cart]
  def  list
    @products = Product.sorted.paginate(:per_page => 5 , :page => params[:page])
  end
  def add_to_cart 
    product = Product.find(params[:id])
    @cart.add_product(product)
    redirect_to(:action => 'show_cart')
  end 
  def show_cart 
  end 

  private 
  def find_or_create_cart
    @cart=session[:cart]||=Cart.new
  end 

end

model

class Cart 
    attr_reader :items
    attr_reader :total_price

def initialize 
    @items = []
    @total_price = 0.0
end 

    def add_product(product)
    @items << LineItem.new_based_on(product)
    @total_price += product.price
end 


end 

Model来自联接表:

class LineItem < ActiveRecord::Base
    belongs_to :order
    belongs_to :product
def self.new_based_on(product)
    line_item = self.new 
    line_item.product = product 
    line_item.quantity = 1
    line_item.price = product.price
    return line_item 
end 

end

这是一个应该在线购物的小应用程序,但是当我点击按钮add to cart时,这将向我的购物车添加两个对象(相同的对象)。希望可以有人帮帮我。

2 个答案:

答案 0 :(得分:0)

我会写另一个答案来解决您的代码问题,但我觉得这可能会对您有所帮助。

我们为我们开发的基于http://firststopcosmeticshop.co.uk

的应用程序开发了我们自己的购物车系统(您可以在Ryan Bates' session models Railscast看到)

如何运作

当使用会话来存储购物车价值时,您基本上存储了来自已添加购物车商品的ID为的会话版本。因为你想让会话保持尽可能薄,所以你只需要一个由产品ID构成的数组:

session[:cart][:products] = [] # -> to init
session[:cart][:products] << product.id # -> builds array like [1,5,6,1,6,4,1,5]

这样您就可以根据需要处理购物车(通过阅读/操作session[:cart][:products]数组)。如果你测试我引用的应用程序,它应该可以帮助你看到它的实际效果

我提到您的代码效率低下,因为您依赖于3个数据源:LineItemCartPublicController。对于基于会话的模型,您真正需要的是CartControllerCartSession。这样您就可以从LineItem致电CartController,让它变得精简


<强>代码

我们基于会话的购物车的工作原理如下:

#app/models/cart_session.rb
class CartSession

#Initalize Cart Session
def initialize(session)
    @session = session
    @session[:cart] ||= {}
end

#Cart Count
def cart_count
    if (@session[:cart][:products] && @session[:cart][:products] != {})
        @session[:cart][:products].count
    else
        0
    end
end

#Cart Contents
def cart_contents
    products = @session[:cart][:products]

    if (products && products != {})

        #Determine Quantities
        quantities = Hash[products.uniq.map {|i| [i, products.count(i)]}]

        #Get products from DB
        products_array = Product.find(products.uniq)

        #Create Qty Array
        products_new = {}
        products_array.each{
            |a| products_new[a] = {"qty" => quantities[a.id.to_s]}
        }

        #Output appended
        return products_new

    end

end

#Qty & Price Count
def subtotal
    products = cart_contents

    #Get subtotal of the cart items
    subtotal = 0
    unless products.blank?
        products.each do |a|
            subtotal += (a[0]["price"].to_f * a[1]["qty"].to_f)
        end
    end

    return subtotal

end

end


#app/controllers/cart_controller.rb
class CartController < ApplicationController
include ApplicationHelper

#Index
def index
    @items = cart_session.cart_contents
    @shipping = Shipping.all
end

#Add
def add
    session[:cart] ||={}
    products = session[:cart][:products]

    #If exists, add new, else create new variable
    if (products && products != {})
        session[:cart][:products] << params[:id]
    else
        session[:cart][:products] = Array(params[:id])
    end

    #Handle the request
    respond_to do |format|
        format.json { render json: cart_session.build_json }
        format.html { redirect_to cart_index_path }
    end
end

#Delete
def delete
    session[:cart] ||={}
    products = session[:cart][:products]
    id = params[:id]
    all = params[:all]

    #Is ID present?
    unless id.blank?
        unless all.blank?
            products.delete(params['id'])
        else
            products.delete_at(products.index(id) || products.length)
        end
    else
        products.delete
    end

    #Handle the request
    respond_to do |format|
        format.json { render json: cart_session.build_json }
        format.html { redirect_to cart_index_path }
    end
end

 end

#config/routes.rb
get 'cart' => 'cart#index', :as => 'cart_index'
post 'cart/add/:id' => 'cart#add', :as => 'cart_add'
delete 'cart/remove(/:id(/:all))' => 'cart#delete', :as => 'cart_delete'

这基本上允许您在简单的会话数组中保留人员购物车项目的列表。然后,该阵列使您能够从阵列中确定数量,产品类型,品牌等。这是最有效的方式,也是我为您的应用推荐的

答案 1 :(得分:0)

要直接解决您的问题,我相信您需要执行以下操作:


<强>路线

#config/routes.rb
resources :cart, only: :index do
   post :add # -> allows you to add an item
end

<强>视图

#app/views/cart/index.html.erb
<% for product in @products do %>
     <%= product.name %>
     <%= product.price %>
<% end %>

<强>控制器

class CartController < ApplicationController
  respond_to :html, :json, :js
  before_action :cart_init, :only => [:add, :index]

  #index should replace show_cart
  def index
    unless @cart.nil?
        @products = Product.find @cart #-> will allow you to find multiple ID's
    end
    respond_with @products
  end

  #KISS (Keep It Simple)
  def add 
    @cart << params[:id]
    respond_with @cart
  end

  private 
  def cart_init
    @cart = session[:cart][:products] ||= Cart.new #-> keep products in its own key. Allows you to add [:cart][:shipping] etc
  end 

end

<强>模型

class Cart 
    attr_reader :items
    attr_reader :total

    def initialize 
        @items = session[:cart][:products] ||= []
        @total = 0.0
     end 
end