RSpec session controler test faild

Witam
Powili przerabiam sobie oficjalny tutorial RoR. Mam klopot przy jednym z testów, jest to test z rozdzialu 9, listingu 9.13:

[code]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[/code]
Test nie przechodzi dostaje info:

[code]Failures:

  1. SessionsController POST ‘create’ with valid email and password should sign the user in
    Failure/Error: controller.current_user.should == @user
    expected: #<User id: 1, name: “Michael Hartl”, email: "mhartl@example.com", created_at: “2010-10-18 17:34:28”,
    updated_at: “2010-10-18 17:34:28”, encrypted_password: “bc370d4fd8b199e6a4a8e93aed5e21e9971f67197bcfad344c9…”,
    salt: “c0ea2938645c213ebb6710b597c7f7a0ce2cc784645bf7d15ed…”>,
    got: nil (using ==)

    ./spec/controllers/sessions_controller_spec.rb:39[/code]

Co jest tego przyczyna? Jak to poprawic?

Pokaż kod kontrolera?

Session controller

[code]class SessionsController < ApplicationController
def new
@title = “Sign in”
end

def create
user = User.authenticate(params[:session][:email],
params[:session][:password])
if user.nil?
# Create an error message and re-render the signin form.
flash.now[:error] = “Invalid email/password combination.”
@title = “Sign in”
render ‘new’
else
# Sign the user in and redirect to the user’s show page.
sign_in user
redirect_to user
end
end

def destroy
end
end[/code]
SessionHelper:

[code]module SessionsHelper

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

def current_user=(user)
@current_user = user
end

def current_user
@current_user ||= user_from_remember_token
end

def signed_in?
!current_user.nil?
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[/code]
W modelu user mam metode:

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

Dorzuć w teście linijkę:

[code=ruby]it “should sign the user in” do
post :create, :session => @attr

response.flash.now[:error].should be_nil

controller.current_user.should == @user
controller.should be_signed_in
end[/code]
Jeśli dostaniesz błąd na tej dodanej linijce to znaczy że masz złe dane w teście. Jeśli nie, to jest coś nie tak z wywołaniem controller.current_user - sprawdź dokładnie czy czegoś nie pominąłeś w tutorialu.

flash.now zwraca blad:

Failure/Error: response.flash.now[:error].should be_nil undefined method `now' for {}:Hash
Sam flash bez ‘now’ przechodzi bez echa. Nadal pojawia sie ten sam blad.

Co to znaczy ze mam zle dane w tescie? Mam teraz dwie bazy danych development i test. Baza test jest pusta. Czy powinien byc w niej record uzytkownika ktorego mam zdefiniowanego w factory? Jest jekies polecenie ktore wypelni mi baze danych, tabele users tym recordem?

rake db:test:clone # Recreate the test database from…
rake db:test:clone_structure # Recreate the test databases fro…
rake db:test:load # Recreate the test database from…
rake db:test:prepare # Check for pending migrations an…
rake db:test:purge # Empty the test database

ogólnie poczytaj to co wypluje
rake --tasks

Dadzą ci one kopie danych z bazy, a do testu z pliku powinno z automatu jak dobrze kojarzę wczytać

Uporalem sie z tematem. Informacja dla innych uzytkownikow.
Sprawe rozwiazalo dodanie “self”:

def sign_in(user) cookies.permanent.signed[:rememember_token] = [user.id, user.salt] self.current_user = user end
Gdzies wyczytałem ze jest to wymagane na “niektórych” systemach, ckolwiek znaczy slowo “niektorych”.

Dygresja: Strasznie mnie drazni ten brak konsekwencji w roznych projektach open source. Skoro framework jest multiplatformowy to ten sam kod ma dzialac na kazdej platformie. Tutaj mamy typowa sytuacje ze srodowiska open source: jeden mowi ze cos nie dziala a drugi na to “u mnie dziala”. Mam nadzieje ze wiecej takich kwiatkow nie spotkam w dalszej przygodzie z rails’ami.

To ktoś coś źle napisał.
Taka konstrukcja w każdym rubim zadziała tak samo - stworzy Ci zmienną lokalną ‘current_user’. Zawsze.

Jak chcesz przypisać coś używając metody current_user=() to musisz użyć tego self. Przypisanie bez selfa => zmienna lokalna.

Z odczytem jest tak: jeśli linijkę wcześniej użyłeś przypisania x=1, to każde następne odwołanie do x będzie oznaczało zmienną o tej nazwie. Jeśli parser nie napotkał przypisania, wtedy będzie szukał metody o tej nazwie.

To dość częsta przyczyna problemów w rubim. Przynajmniej dopóki się człowiek nie przyzwyczai i nie polubi. :wink:

Dzieki za dokladne wyjasnienie. Tego mi brakowalo.