我正在按照第9课进行登录,但登录测试不会通过!我按照代码写了字母,它仍然没有通过。
使用浏览器进行测试时 - 登录无误地运行..
故障:
1)SessionsController使用有效的电子邮件和密码POST'create'应该签署用户 失败/错误:controller.current_user.should == @user 预期:# 得到:零(使用==) './spec/controllers/sessions_controller_spec.rb:55:在'
中的块(4级)2)SessionsController POST'create'使用有效的电子邮件和密码应重定向到用户显示页面 失败/错误:response.should redirect_to(user_path(@user)) 预期块返回真值。 #./spec/controllers/sessions_controller_spec.rb:61:in'块(4级)in'
在5.12秒内完成 7个例子,2个失败
失败的例子:
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
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
会话控制器
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
用户模型
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
会话控制器规范
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
答案 0 :(得分:3)
我假设您已经完成了第9.3.3节并将authenticate
类方法添加到您的用户模型中。
如果您检查身份验证(9.17)类方法,则它具有user = find_by_email(email)
。您应该首先检查您的工厂是否在测试数据库中创建了一个用户。
<强>更新强>
你在SessionsHelper中有这个吗?
def signed_in?
!current_user.nil?
end
更新2
在SessionsHelper !!
中删除以下内容def current_user=(user)
@current_user = user
end
Hartl非常具体地说明为什么要删除这位作家
如果我们这样做,我们将有效地复制其功能 attr_accessor,首先见4.4.5节并用于制作 第7.1.1.7节中的虚拟密码属性问题在于它 完全无法解决我们的问题:使用清单9.15中的代码, 用户的登录状态将被忘记:用户一进入 另一个页面噗! - 会话将结束,用户将会 自动退出。
为了避免这个问题,我们可以找到对应的会话用户 清单9.12中的代码创建的cookie,如清单所示 9.16。
取而代之的是
def current_user
@current_user ||= user_from_remember_token
end
首先,代码清单9.16使用了常见但最初模糊的|| =(“或者 等于“)赋值运算符(方框9.4)。它的作用是设置 @current_user实例变量给用户对应的 记住令牌,但仅限于@current_user未定义.8在其他情况下 单词,构造调用user_from_remember_token方法 第一次调用current_user,但是在后续调用中 返回@current_user而不调用user_from_remember_token。
答案 1 :(得分:1)
我有同样的问题。我也明白它应该被替换。但它不应该both methods are needed。
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= user_from_remember_token
end
答案 2 :(得分:0)
让我永远跟踪这个... ...
rspec错误消息:
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 :
WRONG:
def current_user=(user)
@current_user = user ||= user_from_remember_token
end
RIGHT:
def current_user
@current_user ||= user_from_remember_token
end
当我跟随时,我显然没有给予足够的关注,不幸的是,来自rspec的错误信息并不像通常那样有用。希望这有帮助!