Проблема теста rspec, связанная с cookie, при работе с учебником - PullRequest
2 голосов
/ 15 февраля 2011

Я работал над учебником Майкла Хартла Rails (что, кстати, невероятно круто).

В любом случае, все шло довольно хорошо, и я почти достиг конца главы 10. Проблема в том, что мои тесты rspec начали генерировать некоторые сбои, и я не могу понять, в чем дело.

Первый сбой произошел, когда я работал через раздел об уничтожении пользователей . Тест

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-файлах и обращением к 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 ]

6 голосов
/ 15 февраля 2011

В вашей спецификации вы пытаетесь удалить пользователя, пока вы не авторизованы, поэтому current_user равен nilВы должны запретить доступ к этому действию без подписки пользователя.

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

Так же, как это описано в примере.

0 голосов
/ 13 марта 2011

Я сделал то же упущение, и это исправило сработало. Благодарю. Я согласен с Ducky, урок Майкла Хартла по Rails невероятно хорош. Это почти позор + просто + назвать это "Учебник по Rails". Хотя учебник действительно указывает мне на хорошие привычки разработки на Rails, текст кратко содержит гораздо больше. Очень хорошо сделано.

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