首页 文章

rspec,nil的未定义方法`id':NilClass

提问于
浏览
0
feature "comment" do
 given(:user) do
      build(:user)
 end
 background do
  user1=create(:user)
  user1.id=1
  login_as(user1)     
 end
 scenario "can create comment" do
     @undertake=create(:undertake)
     visit undertake_path(@undertake)
     within("form#undertake-form-test") do
      fill_in "content" , with: "heyheyhey"
     end
     click_button 'send-btn'
     expect(page).to have_content 'heyheyhey'
 end
end

这是spec / features / comment_spec.rb . 以下是controllers / undertakes_controller.rb .

class UndertakesController < ApplicationController
  def show
  @undertake=Undertake.find_by(id: params[:id])
   @comment=current_user.comments.new
end

以下是views / undertakes / show.html.erb .

<p><%= @undertake.id %></p>

和spec / factories / undertakes.rb .

FactoryGirl.define do
  factory :undertake do
    association :ask
    association :user
    id 1
    user_id 2
    ask_id 1
    title "MyString"
    content "MyText"
    result false    
  end
end

的routes.rb

resources :asks , except:[:edit, :update] do 
  resources :undertakes , only:[:create , :show , :destroy] , shallow: true do 
    resources :comments , only:[:create] 
  end 
end

现在,为什么我有错误 ActionView::Template::Error:undefined method id for nil:NilClass . 请帮我 .

1 回答

  • 2

    这里有很多事情可能是潜在的原因,如果不是错误的话,它们是非常单一的 .

    首先,名称 undertake 是错的 . 使用名词形式Undertaking代替型号名称 .

    永远不要使用 find_by(id: params[:id]) . 而是使用 find(params[:id]) ,因为它会引发 ActiveRecord::RecordNotFoundError 并在未找到记录时渲染404页面,而不是用nil错误炸毁 .

    class UndertakingsController < ApplicationController
      def show
        @undertaking = Undertaking.find(params[:id])
        @comment = @undertaking.comments.new
      end
    end
    

    你也应该从 @undertaking 创建评论 - 不要通过表单传递用户ID,因为它让孩子们玩恶搞用户欺骗 .

    而是在创建记录时从会话中分配用户:

    class CommentsController
      # this assumes you are using Devise
      before_action :authenticate_user!
      def create
        @comment = Comment.new(comment_params) do |c|
          c.user = current_user
        end
        # ...
      end
    end
    

    这就是你如何用idiomatically编写规范 . 请注意使用memoized let 帮助程序以及 NEVER 为记录分配id的事实 . 这是由数据库完成的 . 试图手动完成它只会搞砸 .

    require 'rails_helper'
    RSpec.describe 'Comments' do
      let(:current_user) { create(:user) }
      let(:undertaking) { create(:undertaking) }
    
      background do
        login_as(current_user)
      end
    
      scenario "can create a comment" do
        visit undertaking_path(undertaking)
        # Avoid using CSS selectors and instead write specs
        # based on what the user sees as it makes specs brittle
        within("form#undertake-form-test") do
          fill_in "content" , with: "heyheyhey"
          click_button 'Create comment'
        end
        expect(page).to have_content 'heyheyhey' 
      end
    end
    

    使用 let 而不是 @instance 变量 . 在编写功能,请求和控制器规范时,您需要使用 FactoryGirl.create 而不是 build ,因为后者不会插入到数据库中,并且该记录实际上不会存在于您的rails应用程序中 .

    你的工厂定义也严重受损 . 工厂的整个想法是它应该创建独特,有效的记录 . 永远不要在工厂设置ID .

    FactoryGirl.define do
      factory :undertaking do
        title "MyString"
        content "MyText"
        user # just reference the factory if you REALLY need the association to exist
        ask # just reference the factory if you REALLY need the association to exist
        result false # this should probally be set through a DB default instead!
      end
    end
    

相关问题