2010-11-13 6 views
12

Je suis actuellement en cours d'un tutoriel RoR (http://railstutorial.org/chapters/sign-in-sign-out#sec:signin_success est la section pertinente) qui semble être assez bon, même si j'ai rencontré le problème suivant en essayant de voir le site d'exemple .variable locale non définie ou méthode '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 %> 

Comme vous pouvez le voir, le problème provient de ma méthode "signed_in?" qui est censé vérifier si l'utilisateur est connecté ou non en vérifiant si la variable current_user est définie (j'ai inclus le reste du code de l'aide pour donner un contexte, des excuses):

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 

De ma compréhension, .nil? est une méthode qui vérifie si un objet a été défini et, par conséquent, l'objet non défini ne doit pas générer d'erreur mais renvoyer plutôt faux? J'ai cherché le tutoriel pour tous les cas de current_user (avant de vérifier si quelqu'un d'autre avait ce problème avec peu de succès) et mon code semble correct, donc je suis un peu confus et si quelqu'un peut m'aider à comprendre la façon dont les variables Ruby sont supposé être accessible et pourquoi mon code ne fonctionne pas, je serais très reconnaissant.

Edit:

Je ne sais pas s'il est important de portée que je commence juste deux Rails et Ruby, mais le SessionsHelper d'aide est utilisé par mon contrôleur des utilisateurs et des vues (il est inclus dans mes applications contrôleur)

Répondre

7

J'ai couru dans ce même numéro & c'était pour la même raison. Vous avez ignoré une partie des instructions sur 'Listing 9.16'.

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

Vous étiez supposé changer cela en ce qui suit.

def current_user 
    @current_user ||= user_from_remember_token 
end 

Vous devez également remplacer toutes les instances de * self. * Current_user par * @ * current_user.

Une fois que vous faites cela, les erreurs sont résolues.

2

Le néant? La méthode ne va pas vérifier si une variable ou une méthode est définie. Il vérifie uniquement s'il est défini comme un objet nul ou non. Ruby monte la chaine des ancêtres pour SessionsHelper et finalement détermine que current_user n'est défini nulle part (il finira par finir par Kernel # method_missing), puis renvoie une erreur. Le moyen le plus rapide de résoudre le problème serait:

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

ou je crois que vous pourriez faire "@current_user || = user_from_remember_token || false" si vous voulez être plus en ligne avec votre code actuel. – JackCA

+0

Bien que cela arrête certainement l'erreur, il revient constamment faux. Je suppose qu'il est possible qu'il puisse y avoir un problème avec ma méthode de connexion qui fait qu'un current_user ne soit jamais défini, alors c'est probablement mieux pour moi d'y jeter un coup d'œil après une bonne nuit de sommeil. – djlumley

2

J'ai demandé à un ami, et il a corrigé mes erreurs. Je pense qu'une grande partie de mon erreur est venue de ne pas être complètement familier avec la variable variable dans Ruby et d'oublier que tout est un objet et donc la méthode current_user = (user) remplaçait la fonction d'affectation.

La solution de mon ami consistait à changer la portée de current_user en variable instanciée (afin qu'elle puisse être utilisée correctement) et à changer la fonction curent_user = (user) en une fonction simple get_current_user afin de déterminer si l'utilisateur actuel existait dans le cookie.

Le code modifié finale est la suivante:

#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 %> 

Comme vous pouvez le voir la variable a également été changé dans ma tête partielle pour refléter la méthode utilisée dans l'aide pour obtenir l'utilisateur.

va commencer à lire des guides Ruby de base donc la prochaine fois que je reçois dans ma tête, j'ai une idée de l'endroit où commencer le fixer :)

+1

Une meilleure pratique pour l'autorisation Rails serait de nommer la méthode current_user au lieu de get_current_user et de définir une méthode current_user? qui vérifie si current_user est nul ou non. C'est un modèle très commun. –

+0

Y a-t-il une raison particulière à cela? Ou est-ce, comme la plupart des Rails semblent être, juste parce que c'est comme ça que les gens le font? Je peux voir une augmentation de la lisibilité, je me demande simplement s'il y a une autre raison qui me manque. – djlumley

+0

Ce n'est pas seulement une question de Rails. La convention Ruby pour les getters et setters est attribute_name() et attribute_name =(). La possibilité d'ajouter? aux noms de méthodes était intentionnel afin que les développeurs puissent former des questions cohérentes. Ruby est conçu pour être aussi conversationnel que possible. –

4

Assurez-vous que vous avez le code suivant dans le SessionHelper

def current_user=(user) 
    @current_user = user 
end 

def current_user 
    @current_user ||= user_from_remember_token 
end 
Questions connexes