2012-12-19 2 views
3

J'utilise Devise pour authentifier les utilisateurs. J'ai besoin d'afficher/cacher les données basées sur la colonne global_location_id dans toutes mes tables. La valeur de global_location_id va provenir de current_user.global_location_id. J'ai essayé d'ajouter un champ par défaut suivant à l'un de mes modèles:Paramètre dans la portée par défaut dans le modèle

class Artifact < ActiveRecord::Base 
default_scope where(:global_location_id => current_user.global_location_id) 

Mais il donne l'erreur suivante:

undefined local variable or method `current_user' for #<Class:0x8721840> 

Pour contourner la non-disponibilité de current_user dans les modèles j'ajoutés à la suite de mon contrôleur d'application

class ApplicationController < ActionController::Base 
    def set_global_location_id 
    @global_location_id = current_user.global_location_id 
    end 

et a appelé la méthode de mon contrôleur

class ArtifactsController < ApplicationController 
    #Check to see if the user is logged in first 
    before_filter :authenticate_user! 
    before_filter :set_global_location_id 

Changé la portée par défaut dans le modèle d'ajouter @global_location_id

class Artifact < ActiveRecord::Base 
    default_scope where(:global_location_id => @global_location_id) 

Mais cela ne fonctionne pas non plus. L'emplacement @global_location_id est correctement défini dans le contrôleur d'application. Mais il est vide dans le modèle. Comment le faire fonctionner.

Répondre

3

Malheureusement, vous ne pourrez pas partager une variable d'instance qui est définie dans le contrôleur avec une instance du modèle (sans un peu de hackery de threads). C'est en fait une bonne chose parce que sinon cela agirait comme une variable globale, ce qui vous causerait plus de mal que de bien.

J'ai vraiment du mal à comprendre pourquoi vous voudriez le faire de cette façon car cela ajouterait un mauvais couplage entre l'état de l'utilisateur actuellement connecté et votre modèle. Si vous avez essayé de trouver un artefact dans la console, le current_user n'existe pas, et cette variable d'instance ne serait pas disponible, donc vous auriez de sérieux problèmes.

C'est le moment où vous revenez en arrière et vous vous demandez ce que vous essayez réellement de faire. Y a-t-il une raison pour laquelle vous devez faire implicitement le paramètre default_scope en fonction de l'emplacement global_location_id de l'utilisateur actuel? Pourriez-vous simplement créer une portée régulière et l'utiliser dans votre contrôleur à la place?

class Artifact < ActiveRecord::Base 
    scope :by_global_location_id, lambda {|id| where(:global_location_id => id) } 
end 

class ArtifactsController < ApplicationController 
    def index 
    @artifacts = Artifact.by_global_location_id(current_user.global_location_id) 
    end 
end 

L'un des avantages de cette approche est que quelqu'un la lecture de votre code ne doit pas passer une tonne de temps traquer comment le default_scope fonctionne.

Questions connexes