G’day.
Korzystam z has_secure_password (Rails 3.1.1). Napisałem kilka metod pomocniczych w ApplicationHelper:
[code=application_helper.rb]module ApplicationHelper
def current_user=(user)
@current_user = user
end
def current_user
@current_user
end
def sign_in(user)
session[:user_id] = user.id
self.current_user = user
end
def sign_out
session.delete(:user_id)
self.current_user = nil
end
def logged_in?
!self.current_user.nil?
end
def logged_out?
!self.logged_in?
end
end[/code]
[code=sessions_controller.rb]class SessionsController < ApplicationController
def new
end
def create
if user = User.find_by_email(params[:email]).try(:authenticate, params[:password])
sign_in(user)
redirect_to root_url, :notice => t(‘activerecord.messages.session.created’)
else
flash.now.alert = t(‘activerecord.attributes.session.error’)
render :new
end
end
def delete
if logged_in? then
sign_out
flash.notice = t(‘activerecord.messages.session.destroyed’)
else
flash.notice = t(‘app.messages.bad_user’)
end
redirect_to root_path
end
end[/code]
Testuję to w taki sposób:
[code=sessions_controller_spec.rb]describe SessionsController do
render_views
describe “POST create” do
describe "przy niepoprawnych danych" do
before(:each) do
@attr = {
:email => "example@domain.com",
:password => "invalid"
}
end
it "powinien przekierować na stronę logowania i pokazać błąd" do
post :create, @attr
flash.now[:alert].should == I18n.t('activerecord.attributes.session.error')
response.should render_template(:new)
end
end
describe "przy poprawnych danych" do
before(:each) do
@user = Factory(:user,
:email => "joe@example.com",
:password => "abcd",
:password_confirmation => "abcd")
@attr = {
:email => @user.email,
:password => @user.password
}
end
it "powinien zalogować użytkownika" do
post :create, @attr
controller.logged_in?.should == true
end
it "powinien przekierować na stronę główną i wyświetlić wiadomość" do
post :create, @attr
flash[:notice].should == I18n.t('activerecord.messages.session.created')
response.should redirect_to root_path
end
end
end
describe “GET new” do
it “powinno renderować new.html.haml” do
get :new
response.should render_template :new
end
end
describe “DELETE destroy” do
describe “jako niezalogowany” do
it “powinien przekierować na stronę główną z wiadomością” do
controller.should_not be_logged_in
delete :delete
flash[:notice].should == I18n.t(‘app.messages.bad_user’)
response.should redirect_to root_path
controller.should_not be_logged_in
end
end
describe "jako zalogowany" do
it "powinien przekierować na stronę główną z wiadomością" do
valid_user = Factory(:user)
test_login(valid_user)
controller.logged_out?.should == false
delete :delete
controller.logged_out?.should == true
flash[:notice].should == I18n.t('activerecord.messages.session.destroyed')
response.should redirect_to root_path
controller.should_not be_logged_in
end
end
end
end[/code]
I jeszcze w spec_helper.rb mam:
def test_login(user)
controller.sign_in(user)
end
W głównym layoucie w stopce mam informację o tym, czy użytkownik jest zalogowany i jakie jest jego id jeśli jest zalogowany. Pierwszą informację dostaję sprawdzając status logged_in?.
Teraz rzecz najdziwniejsza, wszystkie testy przechodzą bez szemrania, natomiast w przeglądarce po zalogowaniu status w stopce się nie zmienia, czyli jak było “nie” tak dalej jest “nie”, natomiast obok wyświetla się id użytkownika 1, i faktycznie to się zgadza. Czyli wnioskuję z tego, że jakoś źle ustawiam tę zmienną @current_user, tak, że nie jest ona widoczna przez cały czas w całej aplikacji. Prosiłbym o wskazanie źródła problemu.