2010-11-13 16 views
12

Aktualnie przechodzę przez samouczek RoR (http://railstutorial.org/chapters/sign-in-sign-out#sec:signin_success jest odpowiednią sekcją), która wydaje się być całkiem dobra, chociaż napotkam następujący problem podczas próby wyświetlenia przykładowej strony .niezdefiniowana zmienna lokalna lub metoda 'current_user'

Extracted source (around line #10): 

7:   <li><%= link_to "Home", root_path %></li> 
8:   <li><%= link_to "About", about_path %></li> 
9:   
10:    <% if signed_in? %> 
11:     <li><%= link_to "Profile", current_user %></li> 
12:     <li><%= link_to "Sign out", signout_path, :method => delete %></li> 
13:    <% else %> 

Jak widać, problem wynika z mojej metody "signed_in?" która ma na celu sprawdzenie, czy użytkownik jest zalogowany czy nie sprawdzając, czy zmienna jest ustawiona current_user (podaję resztę kodu z pomocnika dać kontekst, przepraszam):

module SessionsHelper 

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

    def sign_out 
    cookies.delete[:remember_token] 
    current_user = nil 
    end 

    def current_user= (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 

Z moje zrozumienie, .nil? jest metodą, która sprawdza, czy obiekt został zdefiniowany, a zatem niezdefiniowany obiekt nie powinien generować błędu, ale raczej zwracać fałsz? Przeszukałem samouczek dla wszystkich przypadków current_user (przed sprawdzeniem, czy ktoś inny miał ten problem z małym sukcesem) i mój kod wydaje się poprawny, więc jestem trochę zdezorientowany i jeśli ktoś jest w stanie mi pomóc zrozumieć, w jaki sposób są zmienne Ruby powinien być dostępny i dlaczego mój kod nie działa, byłbym bardzo wdzięczny.

Edit:

Nie jestem pewien, czy to ważne z zakresu jako Dopiero zaczynam obu szyn i Ruby, jednakże SessionsHelper pomocnik jest używany przez mojego kontrolera użytkowników i odsłon (to jest wliczone w mojej aplikacji kontroler)

Odpowiedz

7

Wpadłem na ten sam numer & z tego samego powodu. Przeoczyłeś część instrukcji na listingu 9.16.

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

Powinieneś to zmienić na następujące.

def current_user 
    @current_user ||= user_from_remember_token 
end 

Będziesz także chciał zmienić wszystkie wystąpienia * self. * Current_user na * @ * current_user.

Po wykonaniu tej czynności problem zostanie rozwiązany.

2

Zera? Metoda nie sprawdza, czy zdefiniowana jest zmienna lub metoda. To wyłącznie sprawdzenie, czy jest zdefiniowany jako obiekt zerowy, czy nie. Ruby podąża za łańcuchem przodków do SessionsHelper iw końcu stwierdza, że ​​current_user nie jest nigdzie zdefiniowany (ostatecznie skończy się na Kernel # method_missing), a następnie zgłasza błąd. Najszybszym sposobem rozwiązania problemu będzie:

#app/helpers/sessions_helper.rb 
def current_user 
    @current_user ||= false 
end 
+0

lub Uważam, że można zrobić "@current_user || = user_from_remember_token || false", jeśli chcesz być bardziej zgodny z bieżącym kodem. – JackCA

+0

Podczas gdy to na pewno zatrzymuje błąd, ciągle zwraca fałszywe. Wydaje mi się, że jest możliwe, że może występować problem z moim podpisywaniem metod, które powodują, że użytkownik current_user nigdy nie zostanie zdefiniowany, więc prawdopodobnie najlepiej będzie, gdy spojrzę na niego po dobrze przespanej nocy. – djlumley

2

Poprosiłem przyjaciela i poprawił moje błędy. Myślę, że duża część mojego błędu pochodziła z tego, że nie znałem w pełni zakresu zmiennego w Ruby i nie pamiętałem, że wszystko jest przedmiotem, a zatem metoda current_user = (użytkownik) nadpisała funkcję przypisania.

Rozwiązaniem mojego przyjaciela było zmienienie zakresu current_user na zmienną instancjonowaną (aby można go było poprawnie używać) i zmianę funkcji curent_user = (user) na prostą funkcję get_current_user w celu ustalenia, czy obecny użytkownik istnieje w pliku cookie.

Ostateczny kod zmienia się w następujący sposób:

#app/helpers/sessions_helper.rb 

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

    def sign_out 
    cookies.delete(:remember_token) 
    @current_user = nil 
    end 

    def get_current_user 
    @current_user ||= user_from_remember_token 
    end 

    def signed_in? 
    !get_current_user.nil? 
    end 

#app/views/layouts/_header.erb 
<% if signed_in? %> 
       <li><%= link_to "Profile", get_current_user %></li> 
       <li><%= link_to "Sign out", signout_path, :method => :delete %></li> 
      <% else %> 
       <li><%= link_to "Sign in", signin_path %></li> 
      <% end %> 

Jak widać zmienną w moim nagłówka częściowego również został zmieniony w celu odzwierciedlenia metodę stosowaną w celu uzyskania pomocnika użytkownikowi.

zamiar zacząć czytać niektóre podstawowe Ruby prowadzi więc następnym razem dostać się nad moją głową mam pomysł gdzie zacząć go naprawić :)

+1

Najlepszą praktyką w autoryzacji Railsów byłoby nazwanie metody current_user zamiast get_current_user i zdefiniowanie metody current_user? który sprawdza, czy current_user jest zerowe czy nie. Jest to bardzo powszechny wzór. –

+0

Czy jest jakiś szczególny powód? A może tak, jak większość Railsów wydaje się być, tylko dlatego, że tak robią ludzie? Widzę wzrost czytelności, zastanawiam się tylko, czy jest inny powód, którego mi brakuje. – djlumley

+0

To nie tylko coś z Railsów. Konwencja Rubinowa dla modułów pobierających i ustawiających to attribute_name() i attribute_name =(). Możliwość dodania? nazwy metod były zamierzone, aby programiści mogli sformułować spójne pytania. Ruby ma być tak rozmowny, jak to możliwe. –

4

Upewnij się, że następujący kod w SessionHelper

def current_user=(user) 
    @current_user = user 
end 

def current_user 
    @current_user ||= user_from_remember_token 
end 
Powiązane problemy