nil的未定义方法:RSpec中的NilClass

时间:2014-02-17 05:53:17

标签: ruby-on-rails ruby rspec

我正在使用RSpec,运行测试时出现此错误:

 Failure/Error: before { get edit_job_path(job) }
 NoMethodError:
   undefined method `jobs' for nil:NilClass
 # ./app/controllers/jobs_controller.rb:63:in `correct_user'
 # ./spec/requests/authentication_pages_spec.rb:35:in `block (6 levels) in <top (required)>'

页面的实际行为(在执行rails服务器时)似乎很好。为什么测试不起作用?我还是Ruby / Rails的初学者,所以任何帮助都会受到赞赏。

一些帮助代码:

authentication_pages_spec.rb

require 'spec_helper'

describe "Authentication" do
  subject { page }

  describe "signin" do
    [...]

    describe "authorization" do
      describe "for non-signed in users" do
        describe "when attempting to visit a protected page" do
          let(:user) { FactoryGirl.create(:user) }
          let(:job) { FactoryGirl.create(:job, user: user) }
          before { get edit_job_path(job) }
          it { should_not have_content('Editing job') }
          describe "after signing in" do
            [...]
          end
          [...]
        end
      end
      [...]
    end
  end
end

jobs_controller.rb

class JobsController < ApplicationController
  before_action :signed_in_user, only: [:new, :create, :update]
  before_action :correct_user, only: [:edit, :update, :destroy]
  before_action :set_job, only: [:show, :edit, :update, :destroy]

  def index
    @jobs = Job.all
  end

  def show
  end

  def new
    @job = Job.new
  end

  def edit
  end

  def create
    @job = current_user.jobs.build(job_params)
    respond_to do |format|
      if @job.save
        format.html { redirect_to @job, notice: 'Job was successfully created.' }
        format.json { render action: 'show', status: :created, location: @job }
      else
        format.html { render action: 'new' }
        format.json { render json: @job.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @job.update(job_params)
        format.html { redirect_to @job, notice: 'Job was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @job.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @job.destroy
    respond_to do |format|
      format.html { redirect_to jobs_url }
      format.json { head :no_content }
    end
  end

  private
    def set_job
      @job = Job.find(params[:id])
    end

    def job_params
      params.require(:job).permit(:title, :org, :internship, :postdate, :filldate, :location, :link, :description)
    end

    def correct_user
      @job = current_user.jobs.find_by(id: params[:id])
      redirect_to root_url, notice: 'You can only edit your own jobs.' if @job.nil?
    end
end

factories.rb

FactoryGirl.define do
  factory :user do
    sequence(:name) { |n| "Johnny #{n}" }
    sequence(:email) { |n| "johnny_#{n}@example.com" }
    password "sampleton"
    password_confirmation "sampleton"
  end

  factory :job do
    sequence(:title) { |n| "Example Title #{n}" }
    user
  end
end

sessions_helper.rb

module SessionsHelper
  [...]

  def current_user=(user)
    @current_user = user
  end

  def current_user
    remember_token = User.encrypt(cookies[:remember_token])
    @current_user ||= User.find_by(remember_token: remember_token)
  end

  [...]

  def signed_in?
    !current_user.nil?
  end

  def signed_in_user
    unless signed_in?
      store_location
      redirect_to signin_url, notice: "Please sign in."
    end
  end

  [...]

  def store_location
    session[:return_to] = request.url if request.get?
  end

  [...]
end

1 个答案:

答案 0 :(得分:1)

你的测试似乎工作正常,因为他们发现了一个错误。您的操作需要设置current_user,而不是,因此您收到错误。

当您点击需要授权的网页时,您需要before_filter重定向您。