Rails:更新购物车中的数量

Ruby新手在这里。 我正在通过Rails进行敏捷Web开发。 在第11章中,它挑战您为购物车中的项目添加“减少数量”按钮。 我继续尝试实现增加链接。

问题是当我点击链接时它没有做任何事情。

line_items_controller.rb

def decrease @cart = current_cart @line_item = @cart.decrease(params[:id]) respond_to do |format| if @line_item.save format.html { redirect_to store_path, notice: 'Item was successfully updated.' } format.js { @current_item = @line_item } format.json { head :ok } else format.html { render action: "edit" } format.json { render json: @line_item.errors, status: :unprocessable_entity} end end end def increase @cart = current_cart @line_item = @cart.increase(params[:id]) respond_to do |format| if @line_item.save format.html { redirect_to store_path, notice: 'Item was successfully updated.' } format.js { @current_item = @line_item } format.json { head :ok } else format.html { render action: "edit" } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end 

cart.rb

 def decrease(line_item_id) current_item = line_items.find(line_item_id) if current_item.quantity > 1 current_item.quantity -= 1 else current_item.destroy end current_item end def increase(line_item_id) current_item = line_items.find(line_item_id) current_item.quantity += 1 current_item end 

的routes.rb

 resources :line_items do put 'decrease', on: :member put 'increase', on: :member end 

_line_item.html.erb

       ×       

/line_items/increase.js.erb

 $('#cart').html(""); $('#current_item').css({'background-color':'#88ff88'}).animate({'background-color':'#114411'}, 1000); 

/line_items/decrease.js.erb

 $('#cart').html(""); $('#current_item').css({'background-color':'#88ff88'}).animate({'background-color':'#114411'}), 1000); if ($('#cart tr').length==1) { // Hide the cart $('#cart').hide('blind', 1000); } 

如果我忘记任何重要的事情,请告诉我。 提前致谢!

– – 编辑 – –

我将代码更改为Rich发布的内容,这是我点击“+”链接时在控制台中显示的内容。

 Started GET "/line_items/25/qty" for ::1 at 2016-01-30 23:49:11 -0600 ActionController::RoutingError (No route matches [GET] "/line_items/25/qty"): 

所以我看到它需要一个数量的路线,但我不太确定如何设置它。 我猜测我们设置的JS警报没有解雇,因为它在这一点上陷入困​​境?

—-编辑2 —-

现在我将链接作为POST传递,并从上下链接中获取此名称错误:

 Started POST "/line_items/25/qty" for ::1 at 2016-01-31 09:49:04 -0600 Processing by LineItemsController#qty as JS Parameters: {"id"=>"25"} Completed 500 Internal Server Error in 38ms (ActiveRecord: 0.0ms) NameError (undefined local variable or method `current_cart' for #): app/controllers/line_items_controller.rb:70:in `qty' 

让我困惑的是current_cartincreasedecrease方法中起作用,但在qty起作用。

使用这种类型的模式,您最好将逻辑分解为单个操作:

 #config/routes.rb resources :line_items do match :qty, action: :qty, via: [:post, :delete], on: :member #-> url.com/line_items/qty end #app/models/line_item.rb class LineItem < ActiveRecord::Base after_update :check_qty, if: "qty_changed?" private def check_qty self.destroy if self.qty.zero? end end #app/controllers/line_items_controller.rb class LineItemsController < ApplicationController def qty @cart = current_cart @item = @cart.line_items.find params[:id] if request.post? #-> increment method = "increment" elsif request.delete? #-> decrement method = "decrement" end @item.send(method, :qty, params[:qty]) respond_to do |format| if @item.save format.html { redirect_to store_path, notice: 'Item was successfully updated.' } format.js { @current_item = @line_item } format.json { head :ok } else format.html { render action: "edit" } format.json { render json: @line_item.errors, status: :unprocessable_entity} end end end end 

这将允许您将单个链接(具有可能的qty )传递给您的控制器。 如果你把它留空,它只会使用1作为数量:

  <%= button_to "+", line_items_qty_path(@line_item), params: { qty: 5 } %> <%= link_to "-", line_items_qty_path(line_item), method: :post, remote: true %> <%= link_to "+", line_items_qty_path(line_item), method: :delete, remote: true %> 

调试

既然你是新手,你需要了解调试

做这样的事情时,有很多地方可能“出错”。 像许多缺乏经验的开发人员一样,你基本上都说“它不起作用”……问题在于许多有经验的开发人员都知道某处存在问题。

你能做的最好的事情是找出它出错的地方。 这是一个繁琐的过程(测试每个部分); 你应该从你的JS开始:

 #app/views/line_items/qty.js.erb alert("test"); 

如果上述情况发生,那就意味着你正在做所有事情。

如果您使用我推荐的代码添加上述文件,我们将更好地了解问题所在。 您还需要发送控制台日志以查找发送到line_items控制器的请求(这将指示Rails是否将请求视为成功)。

一旦找到问题,您就可以确定需要采取哪些措施来解决问题,这是许多人期望问题的基础。


顺便说一下,我们之前已经构建了一个购物车 (它使用的是会话而不是数据库):

在此处输入图像描述

如果你愿意,我可以写出如何做到这一点。 它使用基于会话的模型 。


更新

您看到的错误是因为您通过链接发送了GET请求; 我的路线分别是POSTDELETE 。 您需要以下内容:

  <%= link_to "-", line_items_qty_path(line_item), method: :post, remote: true %> 

我认为我的post中有错误(道歉) – 您必须确保将该method作为POSTDELETE传递


更新2

要初始化current_cart方法,您需要确保它可用。

Ryan Bates在他的“会话模型”Railscast中暗示了这一点 –

 #app/controllers/application_controller.rb class ApplicationController < ActionController::Base before_filter :current_cart helper_method :current_cart private def current_cart @current_cart = session[:cart_id] ? Cart.find(session[:cart_id]) : Cart.create session[:cart_id] = @current_cart.id if @current_cart.new_record? end end 

一段时间过去了,你问这个 – 你解决了吗? 我对这个问题有一个答案 – 我设法增加/减少购物车中的数字,但没有Ajax调用 – 每次点击按钮 – 页面重新加载(我删除了remote: true )。 我没有关注@Richard Peck解决方案,甚至可能是更好的方式。 所以,正如他指出的那样,路由必须使用get方法,而不是put (我不太清楚为什么get而不是post应该使用,但是如果Rails问它我很友好):

  resources :line_items do get 'decrease', on: :member get 'increase', on: :member end 

另外,StackExchange上的其他人注意到我忘了在控制器中允许increase / decrease操作,因为我们默认限制大部分操作:

line_items_controller.rb

  before_action :set_cart, only: [:create, :decrease, :increase] 

所以,我猜这两个问题是你的问题(就像地雷一样)。

line_items_controller.rb:

  def decrease product = Product.find(params[:product_id]) @line_item = @cart.remove_product(product) respond_to do |format| if @line_item.save format.html { redirect_to cart_path, notice: 'Line item was successfully updated.' } format.js format.json { render :show, status: :ok, location: @line_item } else format.html { render :edit } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end def increase product = Product.find(params[:product_id]) @line_item = @cart.add_product(product) respond_to do |format| if @line_item.save format.html { redirect_to :back, notice: 'Line item was successfully updated.' } format.js format.json { render :show, status: :ok, location: @line_item } else format.html { render :edit } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end 

cart.rb

  def add_product(product) current_item = line_items.find_by(product_id: product.id) if current_item current_item.quantity += 1 else current_item = line_items.build(product_id: product.id) end current_item end def remove_product(product) current_item = line_items.find_by(product_id: product.id) if current_item.quantity > 1 current_item.quantity -= 1 elsif current_item.quantity = 1 current_item.destroy end current_item end 

和链接:

 <%= link_to "-", decrease_line_item_path(product_id: line_item.product), class:"btn btn-danger" %> <%= link_to "+", increase_line_item_path(product_id: line_item.product), class:"btn btn-success" %> 

这会成为你需要的吗? 也许任何想法为什么Ajax不工作? 这是一个完整我的问题的链接:

https://stackoverflow.com/questions/40551425/rails-ajax-jquery-cant-make-to-render-changes-without-page-refresh