2011-07-10 16 views
6

Próbuję zbudować system "po prostu kliknij swoje imię aby się zalogować" za pomocą auth_logic. Mój model użytkownika ma adres e-mail i pole nazwy. Aby się zalogować, wystarczy:# <UserSession: {: unauthorized_record => "<protected>"}>

UserSession.create(@user, true) 

Niestety, nie powoduje to utworzenia sesji. Korzystanie z debugera Znalazłem wiadomość:

#<UserSession: {:unauthorized_record=>"<protected>"}> 

Moje modelu użytkownik ma tylko jedną linię:

acts_as_authentic 

linia sesja Filmaster to, co znalazłem gdzieś. Nie jestem pewien, co robi, a ja próbowałem i bez:

class UserSession < Authlogic::Session::Base 
    def to_key 
    new_record? ? nil : [ self.send(self.class.primary_key) ] 
    end 
end 

Baza danych (nie jestem też pewien, czy jest potrzebna, że ​​tabela user_sessions):

create_table "sessions", :force => true do |t| 
    t.string "session_id", :null => false 
    t.text  "data" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" 
add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" 

create_table "user_sessions", :force => true do |t| 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

create_table "users", :force => true do |t| 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    t.string "persistence_token" 
    t.string "email" 
    t.string "name" 
end 

I m przy użyciu Rails 3.0.9 i mój Gemfile mówi (próbowałem zarówno normalne i Authlogic gem Github):

gem 'rails', '3.0.9' 
gem 'sqlite3' 
gem "authlogic" #, :git => 'git://github.com/odorcicd/authlogic.git', :branch => 'rails3' 

Here jest reszta kodu źródłowego.

Miałem ten problem kilka dni temu na podobny projekt i "po prostu odszedł" w pewnym momencie. Po prostu nie pamiętam jak.

Wszelkie pomysły? To doprowadza mnie do szału ...

+0

Sjors Hi, Mam ten sam problem. Czy znalazłeś rozwiązanie tego problemu? – Dorian

+0

@dorian, jeśli potrzebujesz tylko logowania na Twitterze, ten klejnot czyni go banalnym: https://github.com/mislav/twitter-login –

+0

Mając ten sam problem, jak również. Jakieś rozwiązanie? –

Odpowiedz

2

Możliwe rozwiązanie ... wygląda na to, że istnieją dwie wersje tych przykładów metody pomocniczej. Istnieje one że użyliśmy:

@current_user = current_user_session && current_user_session.user 

a następnie jest the newer version że w niektórych nowszych tutoriale i przykłady:

@current_user = current_user_session && current_user_session.record 

Podobno kiedy .user (lub cokolwiek pole logowania) jest wywołany obiekt sesji, zwraca nieautoryzowany_record, podczas gdy .record.user zwraca odpowiednie dane.

+0

Dzięki, przerzuciłem się na używanie klejnotu twitter-login jakiś czas temu, więc nie mogę przetestować twojego rozwiązania. Jestem pewien, że to pomoże komuś. –

1

Niedawno doświadczyłem tego problemu i również się pomyliłem. Odkryłem specyficzny problem mojego kodu, więc jest to kolejne potencjalne rozwiązanie.

tl; dr

nie rozumiałem, że #<UserSession: {:unauthorized_record=>"<protected>"}> jest nadal ważna sesja użytkownika, tylko unauthed który stworzyliśmy sami. Możesz to potwierdzić, dzwoniąc pod numer user, a powinieneś pobrać dowolną instancję User, którą przekazałeś pod adres UserSession.create.

Przyczyna:

Prawdziwym problemem jest dwojaki. Metoda current_user została zbudowana przy założeniu, że bieżący użytkownik nie zmieniłby się podczas okresu ważności żądania i, który wywoływałem current_user przed utworzeniem jednego, aby upewnić się, że już go nie miałem.To może być uproszczone do następującego:

def current_user 
    return @current_user if defined?(@current_user) 

    @current_user = some_method_that_finds_a_proper_user 
end 

Kluczem tutaj jest to, że moja metoda na znalezienie użytkownik może powrócić nil. Gdy tak się stanie, zdefiniuje on @current_user jako nil i dlatego ta wartość w pamięci podręcznej zawsze będzie zwracana podczas kolejnych wywołań.

Solutions

Oto, gdzie robi się nieco trudniejsze, ponieważ tak naprawdę zależy od tego, co potrzebuje Twój kod.

  1. Jeśli nie potrzebujemy current_user po podpisaniu w modelu użytkownika z UserSession.create wtedy nie trzeba robić nic, ale czekać na tynku lub przekierować. Na następną prośbę Twój current_user zostanie poprawnie ustawiony.

  2. Jeśli nie trzeba już sprawdzać dla zalogowanego użytkownika, usuń wszystkie połączenia do current_user przed UserSession.create jeśli stanie a pierwsze wywołanie current_user będzie działać zgodnie z oczekiwaniami.

  3. Zapewnienie łańcucha metoda, która wytwarza current_user albo nie używać buforowania, nie buforują nil S lub zmienić straży tych wartości w pamięci podręcznej, aby ustalić, czy wartość jest truthy zamiast jeśli zmienna instancji jest określona. Strażnik może zostać zmienione na:

    return @current_user if [email protected]_user.nil? # or @current_user.present? in Rails 
    

    Albo można użyć ||= operatora i niejawny zwrot Ruby. Moja uproszczony przykład powyżej może zamiast być:

    def current_user 
        @current_user ||= some_method_that_finds_a_proper_user 
    end 
    

    lub jeśli nie jest to tak proste,

    def current_user 
        @current_user ||= begin 
        some_code 
        doing_many 
        things_here 
        end 
    end 
    
  4. Albo twój problem może być, że masz problemy z pisania test dla tego zachowania. W tym przypadku wolałbym po prostu położyć oczekiwanie na kodzie jak

    expect(UserSession).to receive(:create).with(user) 
    
Powiązane problemy