2010-11-04 6 views
0

Je vais par l'exemple dans le livre Aror: http://media.pragprog.com/titles/rails3/code/e1/views/app/views/test/select.rhtmlpassage des variables pour la présélection sous forme de sélection (Ruby on Rails)

<% @user = "cat" 

def @user.id 
4 
end 

<% form_for :user do |form| %> 
    <%= form.select(:name, %w{ Andy Bert Chas Dave Eric Fred }) %> 
<% end %> 

Dans cet exemple, ressemble @ user.id est hardcoded pour retourner 4. J'ai essayé quelque chose comme:

@temp = 4 

def @user.id 
    @temp 
end 

Cela n'a pas fonctionné ... Comment retourner une variable non globale pour cette fonction particulière?

Répondre

1

Vous devez comprendre que lorsque vous faites "def @ user.id" vous définissez en fait une méthode sur la classe singleton associée à l'objet @user (la classe singleton est également connue sous le nom de "eigenclass" ou "shadow class" "). Alors que faites équivaut à ceci:

@temp = 4 

class << @user 
    def id 
    @temp 
    end 
end 

Comme vous pouvez le voir ci-dessus, la @temp dans la méthode id définition est une variable d'instance régulière, mais il est associé à la classe singleton. En d'autres termes, le @temp à l'intérieur de la définition de l'ID est différent du @temp à l'extérieur. Vous pouvez traiter en réglant directement l'intérieur @temp, comme ceci:

@user.instance_variable_set(:@temp, 4) 

def @user.id 
    @temp 
end 

Laissez-moi savoir si cela aide, ou si vous avez d'autres questions sur la façon dont fonctionne la classe singleton.

0

Cette question n'a vraiment rien à voir avec les formulaires, ou même Ruby on Rails. C'est du pur Ruby.

def @user.id; end est une méthode dite singleton (que vous pouvez lire plus sur here). Maintenant, par défaut, vous ne pouvez pas accéder à des variables d'instance (par exemple @temp) dans une méthode singleton.

Il existe plusieurs façons de contourner ce problème, mais à moins que vous ne souhaitiez spécifiquement créer une méthode singleton dans votre vue (et pourquoi le feriez-vous?), Je recommanderais une autre façon de définir une valeur de présélection. Avec votre exemple, il devrait être aussi simple que:

<% form_for :user do |form| %> 
    <%= form.select(:name, %w{ Andy Bert Chas Dave Eric Fred }, {:selected => @temp}) %> 
<% end %> 

En tant que sidenote; @var est une variable instance dans Ruby - pas une variable globale. Les variables globales commencent par un signe dollar ($var), mais ne l'utilisez pas à moins que vous ne sachiez ce que vous faites.