【问题标题】:Rails Rspec test fail: NoMethodError:Rails Rspec 测试失败:NoMethodError:
【发布时间】:2014-06-29 18:50:15
【问题描述】:

我正在学习 rails,但我不确定为什么会出现此测试失败/错误。任何解释都会很棒!我想要一个解决方案,但我真正需要的是首先了解为什么我会遇到此故障,以便我知道将来如何处理此问题。

Rails 版本是 4.1.1, 红宝石版本 2.0.0p353, Rspec 版本 3.0.1, 水豚2.3.0

这是错误

Failure/Error: click_link "New Todo Item"
 NoMethodError:
   undefined method `todo_item' for nil:NilClass
 # ./app/controllers/todo_items_controller.rb:8:in `new'
 # ./spec/features/todo_items/create_spec.rb:16:in `block (2 levels) in <top (required)>'

这是它所指的控制器 app/controllers/todo_items_controller.rb

class TodoItemsController < ApplicationController
 def index
    @todo_list = TodoList.find(params[:todo_list_id])
 end

 def new
    @todo_item = TodoList.find(params[:todo_list_id])
    @todo_item = @todo_list.todo_items.new  
 end 
end

这是测试 规格/功能/todo_items/create_spec.rb

require 'rails_helper'

describe "Viewing todo items" do 
let!(:todo_list) { TodoList.create(title: "Grocery List", description: "Groceries")}


def visit_todo_list(list)
    visit "/todo_lists"
    within "#todo_list_#{list.id}" do
        click_link "List Items"
    end
end

it "is successful with valid content" do
    visit_todo_list(todo_list)
    click_link "New Todo Item"
    fill_in "Content", with: "Milk"
    click_button "Save"
    expect(page).to have_content("Added Todo List Item.")
    within("ul.todo_items") do
        expect(page).to have_content("Milk")
    end
end
end

这就是与之相伴的观点。 app/views/todo_items/index.html.erb

<h1><%= @todo_list.title %></h1>
<p>testing 123</p>

<ul class="todo_items">
<% @todo_list.todo_items.each do |todo_item| %>
<li><%= todo_item.content %></li>
<% end %>
</ul>

<p>
<%= link_to "New Todo Item", new_todo_list_todo_item_path %>
</p>

如果您需要其他任何东西,请告诉我,并提前感谢您!

最好的,

杰克逊

【问题讨论】:

  • 它告诉你@todo_list 是零。希望你能明白为什么
  • 是的,我明白为什么我在控制器中定义了 `@todo_item 而它应该是 @todo_list。

标签: ruby-on-rails-4 rspec


【解决方案1】:

@todo_item 为 nil,因为您没有在新方法中定义 @todo_list。您希望您的新方法如下所示:

def new
  @todo_list = TodoList.find(params[:todo_list_id])
  @todo_item = @todo_list.todo_items.new  
end 

但是,这并不是很干,因为您已经在索引方法中定义了@todo_list。您应该创建一个名为 set_list 的新方法,然后使用 before_action 在相关方法之前调用它。

before action :set_list

def new
  @todo_item = @todo_list.todo_items.new 
end

private
  def set_list
    @todo_list = TodoList.find(params[:todo_list_id])
  end

【讨论】:

  • 哦,好的!天哪,所以我首先定义了 todo_item 而不是 todo_list。现在我明白了.. 这么简单的错误。谢谢!
猜你喜欢
  • 1970-01-01
  • 2016-12-20
  • 2020-08-18
  • 2013-01-06
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多