首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails by Example (由Michael Hartl编写),第9课,登录测试无法通过

Rails by Example (由Michael Hartl编写),第9课,登录测试无法通过
EN

Stack Overflow用户
提问于 2011-09-30 17:33:18
回答 3查看 2.1K关注 0票数 0

我正在学习第9课的登录,但是登录测试就是不能通过!我严格遵循代码,但它仍然不能通过。

使用浏览器进行测试时-登录工作正常,没有错误。

失败:

1)应使用有效的电子邮件和密码创建POST 'create‘,并在失败时对用户进行签名/Error: controller.current_user.should == @user expected:# got: nil (using ==) # `block ``block (4 levels) in’

2)使用有效电子邮件和密码的SessionsController POST 'create‘应重定向到用户显示页面失败/错误: response.should redirect_to(user_path(@ user ))预期块返回真值。# ./spec/controllers/sessions_controller_spec.rb:61:in ` `block (4 levels) in‘

5.12秒内完成7例,2次失败

失败示例:

代码语言:javascript
复制
rspec ./spec/controllers/sessions_controller_spec.rb:53 # SessionsController POST 'create' with valid email and password should sign the user in
rspec ./spec/controllers/sessions_controller_spec.rb:59 # SessionsController POST 'create' with valid email and password should redirect to the user show page

如您所见,由于某种原因,测试controller.current_user.should == @user返回nil。

请帮助我理解这一点..

谢谢

SessionHelper

代码语言:javascript
复制
    module SessionsHelper

 def sign_in(user)
    cookies.permanent.signed[:remember_token] = [user.id, user.salt]
    self.current_user= user
     end


def signed_in?
    !self.current_user.nil?
end
def current_user=(user)
    @current_user = user
end

 def current_user
    @current_user ||= user_from_remember_token
end

  private

def user_from_remember_token
  User.authenticate_with_salt(*remember_token)
end

def remember_token
  cookies.signed[:remember_token] || [nil, nil]
end
   end

会话控制器

代码语言:javascript
复制
    class SessionsController < ApplicationController
     def new
       @title = "Sign In"
       end

    def create
    user = User.authenticate(params[:session][:email], params[:session][:password])
    if user.nil?
        flash.now[:error] = "Invalid email/password"

        @title = "Sign In (right this time)"
        render 'new'
    else
        #sign in the user
        sign_in @user
        redirect_to user

    end
end

def destroy

end
   end

用户模型

代码语言:javascript
复制
   require 'digest'
    class User < ActiveRecord::Base

attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation


email_regex =  /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i



validates :name, :presence => true,
                        :length => {:minimum => 2, :maximum => 50}
validates :email, :presence => true, :format => {:with => email_regex}, :uniqueness => {:case_sensitive => false }

#Automatically creates the virtual password confimration attribute
validates :password, :presence => true,
                                :confirmation => true,
                                :length => {:within => 6..40}


before_save :encrypt_password

def has_password?(submitted_password)
    self.salt = make_salt if new_record?
    encrypted_password == encrypt(submitted_password)
end

def self.authenticate(email, submitted_password)
    user = find_by_email(email)
    return nil if user.nil?
    return nil if user.has_password?(submitted_password)
end

 def self.authenticate_with_salt(id, cookie_salt)
    user = find_by_id(id)
    (user && user.salt == cookie_salt) ? user : nil
end


     private

def encrypt_password
  self.salt = make_salt unless has_password?(password)
  self.encrypted_password = encrypt(password)
end

def encrypt(string)
  secure_hash("#{salt}--#{string}")
end

def make_salt
  secure_hash("#{Time.now.utc}--#{password}")
end

def secure_hash(string)
  Digest::SHA2.hexdigest(string)
end
   end

会话控制器规范

代码语言:javascript
复制
require 'spec_helper'

describe SessionsController do
render_views


  describe "GET 'new'" do
    it "should be successful" do
      get 'new'
      response.should be_success
    end

    it "should have the right title" do
        get :new
        response.should have_selector("title", :content => "Sign In")
    end



  end

  describe "POST 'create'" do

        describe "invalid login" do
            before(:each) do
                @attr = {:email => "email@example.com", :password => "invalid"}
            end

            it "should re-render the new page" do
                post :create, :session => @attr
                response.should render_template('new')
            end

            it "should have the right title" do
                post :create, :session => @attr
                response.should have_selector("title", :content => "Sign In (right this time)")
            end

            it "should have flash.now message" do
                post :create, :session => @attr
                flash.now[:error].should =~ /invalid/i
            end
        end

        describe "success" do

            before(:each) do
                @user = Factory(:user)
                @attr = { :email => @user.email, :password => @user.password }
            end

            it "should sign the user in" do
                post :create, :session => @attr
                controller.current_user.should == @user
                controller.should be_signed_in
            end

            it "should redirect to the user show page" do
                post :create, :session => @attr
                response.should redirect_to(user_path(@user))
            end
        end

    end

end
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-30 18:36:06

我假设您已经完成了9.3.3节,并将authenticate类方法添加到您的用户模型中。

如果您检查您的身份验证(9.17)类方法,它具有user = find_by_email(email)。您应该首先检查您的工厂是否确实在测试数据库中创建了一个用户。

更新

这个在SessionsHelper有吗?

代码语言:javascript
复制
def signed_in?
  !current_user.nil?
end

更新2

删除SessionsHelper中的以下内容!!

代码语言:javascript
复制
def current_user=(user)
    @current_user = user
end

Hartl非常具体地说明了为什么要删除这个编写器

如果我们这样做,我们将有效地复制attr_accessor的功能,该功能在4.4.5节中首次出现,并在7.1.1.7节中用于创建虚拟密码属性。问题是它完全不能解决我们的问题:使用清单9.15中的代码,用户的登录状态将被遗忘:一旦用户转到另一个页面--the会话将结束,用户将自动注销。

为了避免这个问题,我们可以找到与清单9.12中的代码创建的cookie相对应的会话用户,如清单9.16所示。

它将被替换为

代码语言:javascript
复制
def current_user
  @current_user ||= user_from_remember_token
end

首先,清单9.16使用了常见但最初模糊的||= (“or

”)赋值运算符(方框9.4)。它的作用是将@current_user实例变量设置为与记忆标记对应的用户,但仅当@current_user未定义时。8换句话说,该构造在第一次调用current_user时调用user_from_remember_token方法,但在随后的调用中返回@current_user,而不调用user_from_remember_token。

票数 3
EN

Stack Overflow用户

发布于 2011-10-18 06:40:42

我也有同样的问题。我也理解它应该被替换。但它不应该both methods are needed

代码语言:javascript
复制
def current_user=(user)
  @current_user = user
end

def current_user
  @current_user ||= user_from_remember_token
end 
票数 1
EN

Stack Overflow用户

发布于 2012-07-28 14:15:39

我花了很长时间才找到这个人...

rspec错误消息:

代码语言:javascript
复制
 1) SessionsController POST 'create' with valid email and password should sign the user in
     Failure/Error: controller.current_user.should == @user
     NoMethodError:
       undefined method `current_user' for #<SessionsController:0x00000005426eb8>
     # ./spec/controllers/sessions_controller_spec.rb:51:in `block (4 levels) in <top (required)>'

您想要编辑app/helpers/sessions_helper.rb

错误:

代码语言:javascript
复制
def current_user=(user)
    @current_user = user ||= user_from_remember_token
end

右图:

代码语言:javascript
复制
def current_user
    @current_user ||= user_from_remember_token
end

很明显,在我跟随本文的过程中,我没有给予足够的关注,不幸的是,来自rspec的错误消息并没有像通常那样有帮助。希望这能有所帮助!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7608499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档