2010-03-10 7 views
19

J'essaie d'accéder à une variable d'instance qui est définie dans le contrôleur du modèle. Le contrôleur est le contrôleur de produits et le modèle est le modèle de produits. La variable d'instance est une instance d'un autre modèle appelé compte.Ruby on Rails - Variable de contrôleur d'accès du modèle

La variable d'instance est @current_account

Quand je lance rien de code se produit, je ne reçois pas une erreur. Est-ce que quelqu'un sait où je peux trouver quelque chose de lu sur les variables d'instance d'accès définies dans le contrôleur à partir du modèle?

Merci

Eef

+0

Vous essayez donc d'accéder à la variable @current_account dans un modèle? La variable @current_account est définie dans un contrôleur? – Steve

Répondre

46

Vous ne devriez généralement pas essayer d'accéder au contrôleur à partir du modèle pour les problèmes d'esprit que je n'aborderai pas.

Je résolu un problème similaire comme ceci:

class Account < ActiveRecord::Base 
    cattr_accessor :current 
end 

class ApplicationController < ActionController::Base 
    before_filter :set_current_account 
    def set_current_account 
    # set @current_account from session data here 
    Account.current = @current_account 
    end 
end 

Ensuite, il suffit d'accéder au compte courant avec Account.current

+11

Les variables de classe ne sont-elles pas partagées entre toutes les demandes ?! – vise

+0

Je ne comprends pas comment obtenir la valeur de la variable à partir du: symbole courant dans le modèle? J'ai essayé Account.current et actuel. – djburdick

+0

Quelle est la différence entre 'cattr_accessor' et' attr_accessor'? – user94154

1

Je ne suis pas sûr si je comprends bien la question exactement, mais je vais prendre un coup de poignard.

Je pense que si vous devez accéder à une variable d'instance de contrôleur à partir du modèle, vous devez soit en faire un attribut dans le modèle, soit déplacer votre logique vers l'autre contrôleur de classe, et non vers le modèle.

5

Si vous besoin d'accéder à une variable de commande à partir d'un modèle, il signifie généralement que votre conception est mal parce qu'un contrôleur sert de pont entre la vue et le modèle (au moins dans Rails), le contrôleur obtient des informations des modèles, les modèles ne devraient rien savoir des contrôleurs, mais si vous voulez le faire de toute façon, jeem dit, mais je préfère faire:

class << self 

    attr_accessor :current 

end 

au lieu de

cattr_accessor :current

vous pouvez voir pourquoi ici =>cattr_accessor doesn't work as it should

+0

Ce n'est pas beaucoup mieux car c'est toujours partagé entre les requêtes, sans parler de la sécurité des threads. Cela devrait être soit un attribut sur une instance d'utilisateur, soit vous devriez le passer aux méthodes qui ont besoin de le connaître. – gtd

2

Je ne peux pas commenter directement si je posterai ici: la réponse acceptée ne semble pas avoir raison. Comme le remarque @vise, les variables de classe sont partagées entre les requêtes. Donc, à moins qu'il n'y ait qu'un seul compte courant pour l'application entière, cela ne se comportera pas comme prévu.

Pour plus, voir la réponse acceptée par @molf ici: Is Rails shared-nothing or can separate requests access the same runtime variables?

8

AVERTISSEMENT: Le casse code suivant les conventions MVC, qui a dit ...

En utilisant les attributs de classe peuvent probablement conduire à enfiler la sécurité problèmes. J'utiliser Thread.current + around_filter au contrôleur de stocker les données relatives au niveau de fil, et assurer qu'il est effacé juste avant la demande se termine:

class ApplicationController < ActionController::Base 

    around_filter :wrap_with_hack 

    def wrap_with_hack 
    # We could do this (greener solution): 
    # http://coderrr.wordpress.com/2008/04/10/lets-stop-polluting-the-threadcurrent-hash/ 
    # ... but for simplicity sake: 
    Thread.current[:controller] = self 
    begin 
     yield 
    ensure 
    # Prevent cross request access if thread is reused later 
    Thread.current[:controller] = nil 
    end 
    end 
end 

Maintenant, l'instance de contrôleur sera avaliable globaly lors du traitement de la demande par l'intermédiaire Thread.current [: controller]

+0

Salut @ibaixas merci pour cela. Mais pouvez-vous s'il vous plaît expliquer comment l'attribut class mènera à un problème de sécurité de thread. Je suis un débutant. Ce problème existe-t-il également dans Rails 4? – Akshat

+1

Les variables de classe sont partagées entre les threads. Cela signifie que lorsque vous utilisez un serveur d'applications multithread comme puma, différents threads gérant différentes requêtes vont stocker l'instance du contrôleur dans la même variable, en s'encastrant mutuellement. En utilisant le hash Thread.current, vous vous assurez que la variable n'est définie que par le thread en cours. Désolé pour le délai (2 ans) ... – ibaixas

Questions connexes