通过教程工作时Cookie相关的rspec测试问题

时间:2011-02-15 04:35:21

标签: ruby-on-rails ruby-on-rails-3 rspec

我一直在研究Michael Hartl的Rails tutorial(顺便说一下,这真是令人难以置信的棒极了)。

无论如何,一切都进行得很顺利,我几乎已经到了第10章的末尾。问题是我的rspec测试已经开始产生一些失败,我无法弄清楚出了什么问题。

第一次失败发生在the section on destroying users时。测试

before :each do
  @user = Factory :user
end

describe "as a non-signed-in user" do
  it "should deny access" do
    delete :destroy, :id => @user
    response.should redirect_to(signin_path)
  end
end

给出错误:

UsersController DELETE 'destroy' as a non-signed-in user should deny access
 Failure/Error: delete :destroy, :id => @user
 NoMethodError:
   undefined method `admin?' for nil:NilClass
 # ./app/controllers/users_controller.rb:76:in `admin_user'
 # ./spec/controllers/users_controller_spec.rb:308:in `block (4 levels) in <top (required)>'

这是消息在users_controller中引用的代码:

def admin_user
  # the error tels me that current_user = NilClass
  redirect_to(root_path) unless current_user.admin?
end

所以我猜这会表明current_user无法正常工作并且设置为nil。现在current_user涉及SessionsHelper的许多方法,其中(afaik)处理在安全cookie中设置用户ID并在cookie在网站中移动时引用cookie。所以这表明cookie存在问题。

我已经检查了浏览器并且正在设置cookie,我还查看了代码的每个部分,它完全复制了教程,就我所知。

我还应该关注其他什么吗?

附录

以下是SessionsHelper模块的内容:

module SessionsHelper

    def sign_in user
        # rails represents cookies as a hash and deals with the conversion for us
        # making the cookie "signed" makes it impervious to attack
        cookies.permanent.signed[:remember_token] = [user.id, user.salt]
        # this line calls the assignment operator below
        self.current_user = user
      end

      def current_user=(user)
        @current_user = user
      end

      # this is a getter method
      def current_user
        # this sets @current_user = to the user corresponding to the remember token
        # but only if @current user is undefined. ie it only works once
        @current_user ||= user_from_remember_token
      end

    def signed_in?
        # return true if current_user is not nil
        !current_user.nil?
      end

      def sign_out
        cookies.delete(:remember_token)
        self.current_user = nil
      end

      def current_user? user
        # returns true if the user object == the current_user object
        user == current_user
      end

      def authenticate
        deny_access unless signed_in?
      end

    def deny_access
        store_location
        # this is a shortcut for flash notices: flash[:notice] = "Please sign in to access this page."
        redirect_to signin_path, :notice => "Please sign in to access this page."
      end

      def redirect_back_or(default)
        redirect_to(session[:return_to] || default)
        clear_return_to
      end

  private

    def user_from_remember_token
      # the * allows us to give a 2 element array to a method expecting 2 seperate arguments
      User.authenticate_with_salt(*remember_token)
    end

    def remember_token
      # return [nil, nil] if the :remember_token cookie is nil
      cookies.signed[:remember_token] || [nil, nil]
    end

    def store_location
      # stores the url the browser was requesting
      session[:return_to] = request.fullpath
    end

    def clear_return_to
      session[:return_to] = nil
    end
  end

2 个答案:

答案 0 :(得分:6)

在你的规范中,你正在尝试删除用户,而你没有登录,所以current_user是零。您应该阻止在用户中访问此操作。

class UsersController < ApplicationController
  before_filter :authenticate, :only => [:index, :edit, :update, :destroy]
  ....

正如示例中所述。

答案 1 :(得分:0)

我做了同样的疏忽,这个修复工作。谢谢。我同意ducky,Michael Hartl的Rails教程非常棒。 + +只是称它为“Rails教程”几乎是一种耻辱。虽然本教程确实似乎指向了良好的Rails开发习惯,但文本简明扼要地包含了更多内容。做得很好。