Je rencontre un problème de portée qui empêche les variables d'instance d'être initialisées correctement par les helpers appelés depuis la vue.Ruby on Rails: Initialisation des variables d'instance avec les assistants en vue
#sample_controller.rb
class SampleController < ApplicationController
def test
end
end
#application_controller.rb
helper_method :display
def display
if not defined? @display
return @display = "a"
else
return @display += "a"
end
end
#test.html.erb
<%= display %>
<%= display %>
<%= @display %>
<%= @display.reverse %>
Lorsque l'échantillon/test est affiché, il meurt avec une erreur "tout en évaluant nil.reverse". C'est surprenant car les deux premiers appels à afficher auraient dû initialiser @display j'aurais pensé. Si <% = @ display.reverse%> est supprimé, la sortie est "aa", indiquant que la variable d'instance @display est définie par la méthode d'assistance, mais qu'il n'y a pas d'accès dans la vue.
Si le contrôleur est modifié de façon à devenir (avec le code de la vue originale):
class SampleController < ApplicationController
def test
display
end
end
La sortie devient "aaa a un". Si je fais 2 appels à afficher dans le contrôleur, je reçois, "aaa aaaa aa aa". Il semble donc que seuls les appels effectués dans le contrôleur modifieront la variable d'instance SampleController, tandis que les appels dans la vue modifieront une variable d'instance pour ApplicationController à laquelle la vue n'a pas accès.
Est-ce un bug dans Rails ou est-ce que je suis mal compris et c'est pour une raison ou pour une autre?
Le contexte dans lequel j'ai rencontré ce bogue est d'essayer de créer un login_in? Méthode ApplicationController qui configure une variable @user la première fois qu'elle est appelée et renvoie true ou false si un utilisateur est connecté. Cela ne fonctionnerait que si j'ajoutais un appel inutile dans le contrôleur avant de tenter de l'utiliser dans la vue.
Donc dans ma vraie application, @display est en fait @user, et il est utilisé pour afficher des informations sur l'utilisateur. À titre d'exemple de ce que je veux dire, le code typique est quelque chose comme, <% if logged_in?%><% = @ User.name%><%end%>. Alors, est-ce la meilleure façon de faire cela pour avoir un appel before_filter dans le ApplicationController qui configure la variable @user? Parce que souvent, pour une vue donnée, la seule utilisation de @user est pour quelque chose comme je l'ai décrit ci-dessus, et il n'y a pas d'autre besoin pour qu'il soit utilisé dans le contrôleur lui-même. –
Oui, le mécanisme de copie d'ivar correspond à ce que vous décrivez. Configurez @user dans un filtre avant. – ffoeg
Merci @ffoeg, cette réponse est très utile. Pouvez-vous pointer vers une documentation ou des guides de rails où cela est expliqué? On ne sait pas quelles variables sont partagées entre View, Controller et Helpers. – CodeKid