我是一名初学者,通过使用Rails 4进行敏捷Web开发,我们(读者)构建了一个购物车风格的演示应用程序。因此,主要的REST资源是1)产品,2)推车和3)订单项。这是我在学习Rails的过程中的第二个演示/示例应用程序,到目前为止,一切看起来都是直截了当的,除了我在测试中的 update 行动中一直出现错误物品控制器。我不确定它是否与测试本身,实际控制器动作和/或我的灯具设置有关。 (我第一次使用"内置" MiniTest和灯具;之前的示例应用我使用了RSpec和FactoryGirl。)
错误(不是失败)我看起来像这样:
Finished tests in 0.936959s, 26.6821 tests/s, 56.5660 assertions/s.
1) Error:
LineItemsControllerTest#test_should_update_line_item:
ActionController::ActionControllerError: Cannot redirect to nil!
app/controllers/line_items_controller.rb:54:in `block (2 levels) in update'
app/controllers/line_items_controller.rb:52:in `update'
test/controllers/line_items_controller_test.rb:38:in `block in <class:LineItemsControllerTest>'
25 tests, 53 assertions, 0 failures, 1 errors, 0 skips
我不清楚为什么我会重定向到零。路径不好吗?或者它是路径末端的对象?和/或&#34;其他&#34;?我不容易在控制器本身看到任何看起来像问题的东西(无论如何,我已经包含下面的代码),所以我怀疑它与测试文件或灯具设置有关。我已经尝试过填写各种“假人”。 (例如,product_id: 55
)和&#39;引用&#39; (例如,product_id: products(:ruby).id
)line_items.yml灯具中的值没有成功。
我还在控制器测试设置中尝试了不同的内容,例如引用订单项所属的其他灯具类型(产品和购物车)中的特定灯具ID(与上述相同的想法) )。我也尝试过以多种方式编辑更新测试,包括尝试重定向到订单项的购物车而不是line_items_path,例如:
assert_redirected_to cart_path(assigns(:line_item).cart)
......而不是......
assert_redirected_to line_item_path(assigns(:line_item))
还尝试了定义的变体:line_item,我将其作为更新的对象,例如:
patch :update, id: @line_item, line_item: { product_id: products(:ruby).id }
......而不是......
patch :update, id: @line_item, line_item: { product_id: @line_item.product_id }
我认为相关的代码包含在下面。非常感谢任何帮助!
line_items_controller.rb
class LineItemsController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:create]
before_action :set_line_item, only: [:show, :edit, :update, :destroy]
# GET /line_items
# GET /line_items.json
def index
@line_items = LineItem.all
end
# GET /line_items/1
# GET /line_items/1.json
def show
end
# GET /line_items/new
def new
@line_item = LineItem.new
end
# GET /line_items/1/edit
def edit
end
# POST /line_items
# POST /line_items.json
def create
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product.id)
respond_to do |format|
if @line_item.save
format.html { redirect_to @line_item.cart,
notice: 'Line item was successfully created.' }
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
session[:count] = nil
end
# PATCH/PUT /line_items/1
# PATCH/PUT /line_items/1.json
def update
respond_to do |format|
if @line_item.update(line_item_params)
format.html { redirect_to @line_item.cart,
notice: 'Line item was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @line_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /line_items/1
# DELETE /line_items/1.json
def destroy
@line_item.destroy
respond_to do |format|
format.html { redirect_to line_items_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line_item
@line_item = LineItem.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_item_params
params.require(:line_item).permit(:product_id)
end
end
line_items_controller_test.rb
require 'test_helper'
class LineItemsControllerTest < ActionController::TestCase
setup do
@line_item = line_items(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:line_items)
end
test "should get new" do
get :new
assert_response :success
end
test "should create line_item" do
assert_difference('LineItem.count') do
post :create, product_id: products(:ruby).id
end
assert_redirected_to cart_path(assigns(:line_item).cart)
end
test "should show line_item" do
get :show, id: @line_item
assert_response :success
end
test "should get edit" do
get :edit, id: @line_item
assert_response :success
end
test "should update line_item" do
patch :update, id: @line_item, line_item: { product_id: @line_item.product_id }
assert_redirected_to line_item_path(assigns(:line_item))
end
test "should destroy line_item" do
assert_difference('LineItem.count', -1) do
delete :destroy, id: @line_item
end
assert_redirected_to line_items_path
end
end
line_items.yml
one:
product_id: #Trying values here doesn't seem to help.
cart_id: #Trying values here doesn't seem to help.
two:
product_id:
cart_id:
products.yml
one:
title: MyString
description: MyText
image_url: MyString
price: 9.99
two:
title: MyString
description: MyText
image_url: MyString
price: 9.99
ruby:
title: Programming Ruby 1.9
description:
Ruby is the fastest growing and most exicting dynamic
language out there. If you need to get working programs
delivered fast, you should add Ruby to your toolbox.
price: 49.50
image_url: ruby.png
three:
title: MyString
description: MyText
image_url: MyString
price: 9.99
carts.yml
one: {}
# column: value
#
two: {}
# column: value
答案 0 :(得分:1)
在line_items_controller.rb
中,您使用Rails资源表示法重定向回购物车页面。有问题的订单项是:one
,其中没有关联的购物车。尝试通过修改line_item.yml
来分配一个,如下所示:
one:
product: one
cart: one
我认为 Rails应该足够聪明,分别知道这些作业需要Product
和Cart
,但如果没有,您可以尝试使用更具描述性的内容/固定装置的唯一标签::cart_one
,:product_one
甚至:joes_cart
,:bobs_cart
等。
答案 1 :(得分:0)
您的订单项在line_items.yml中没有ID。像这样做
<强> line_item.yml 强>
one:
id: 1
product_id: #Trying values here doesn't seem to help.
cart_id: #Trying values here doesn't seem to help.
two:
id: 2
product_id:
cart_id:
您还尝试在测试中传递整个对象而不是id。只需传递id:
patch :update, id: @line_item.id, line_item: { product_id: @line_item.product_id }
你不应该试图发布整个对象。发布对象ID