同时有两个物品没有一个添加到我的购物车中。这是controller
和models
:
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
时,这将向我的购物车添加两个对象(相同的对象)。希望可以有人帮帮我。
答案 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个数据源:LineItem
,Cart
和PublicController
。对于基于会话的模型,您真正需要的是CartController
和CartSession
。这样您就可以从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