Rails by Example (by Michael Hartl), урок 9, тесты входа не пройдут - PullRequest
0 голосов
/ 30 сентября 2011

Я следую уроку 9 для входа, но тест на вход просто не пройдет! Я следовал за кодом к письму, и он все еще не пройдет.

при тестировании в браузере - вход работает без ошибок ..

Неудача:

1) SessionsController POST 'create' с действительным адресом электронной почты и паролем должен подписать пользователя в Ошибка / Ошибка: controller.current_user.should == @user ожидается: # получил: ноль (используя ==) # ./spec/controllers/sessions_controller_spec.rb:55:in `блок (4 уровня) в '

2) SessionsController POST 'create' с действительным адресом электронной почты и паролем следует перенаправить на страницу показа пользователя. Ошибка / Ошибка: response.should redirect_to (user_path (@user)) Ожидаемый блок для возврата истинного значения. # ./spec/controllers/sessions_controller_spec.rb:61:in `блок (4 уровня) в '

Завершено за 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 по какой-то причине возвращает ноль.

Пожалуйста, помогите мне понять это ..

Спасибо

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

Ответы [ 3 ]

3 голосов
/ 30 сентября 2011

Я предполагаю, что вы завершили предыдущий Раздел 9.3.3 и добавили метод класса authenticate в свою модель пользователя.

Если вы проверите свой метод класса 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

Хартл весьма конкретно объясняет, почему этот писатель удален

Если бы мы сделали это, мы бы эффективно скопировали функциональность attr_accessor, впервые увиденную в Разделе 4.4.5 и использовавшуюся для создания атрибута виртуального пароля в Разделе 7.1.1.7. Проблема в том, что он полностью не может решить нашу проблему:код в листинге 9.15, статус входа пользователя будет забыт: как только пользователь перейдет на другую страницу - poof! - сеанс завершится и пользователь автоматически выйдет из системы.

Чтобы избежать этой проблемымы можем найти пользователя сеанса, соответствующего файлу cookie, созданному кодом в листинге 9.12, как показано в листинге 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 голос
/ 18 октября 2011

У меня была такая же проблема.Я также понял, что его следует заменить.Но это не должно оба метода необходимы .

def current_user=(user)
  @current_user = user
end

def current_user
  @current_user ||= user_from_remember_token
end 
0 голосов
/ 28 июля 2012

У меня ушло навсегда, чтобы отследить это ...

Сообщение об ошибке 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 / session_helper.rb :

НЕПРАВИЛЬНО:

def current_user=(user)
    @current_user = user ||= user_from_remember_token
end

ПРАВО:

def current_user
    @current_user ||= user_from_remember_token
end

Я явно не уделял достаточно внимания, когда следил, и, к сожалению, сообщение об ошибке отrspec был не так полезен, как обычно.Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...