2009-07-02 7 views
1

Fondamentalement, je veux implémenter une extension Rails simple pour définir la gravité des méthodes dans mon contrôleur afin que je puisse en restreindre l'utilisation de façon appropriée. Par exemple, je voudrais définir les actions reposant par défaut comme si dans un résumé superclasse:Ruby on Rails pour définir les paramètres par défaut des classes et autoriser un remplacement des sous-classes

view_methods :index, :show 
edit_methods :new, :create, :edit, :update 
destroy_methods :destroy 

Je puis dans un appel de commande non abstraite:

edit_methods :sort 

à ajouter dans la méthode de tri sur ce contrôleur particulier comme étant une méthode de niveau d'édition.

Je pourrais alors utiliser un before_filter pour vérifier le niveau de l'action en cours d'exécution, et l'abandonner si ma logique détermine que l'utilisateur actuel ne peut pas le faire.

Le problème, c'est que j'ai de la difficulté à déterminer comment mettre en place ce type de structure. J'ai essayé quelque chose comme ça jusqu'à présent:

class ApplicationController 

    @@view_methods = Array.new 
    @@edit_methods = Array.new 
    @@destroy_methods = Array.new 

    def self.view_methods(*view_methods) 
    class_variable_set(:@@view_methods, class_variable_get(:@@view_methods) << view_methods.to_a) 
    end 

    def self.edit_methods(*edit_methods) 
    class_variable_set(:@@edit_methods, self.class_variable_get(:@@edit_methods) << edit_methods.to_a) 
    end 

    def self.destroy_methods(*destroy_methods) 
    @@destroy_methods << destroy_methods.to_a 
    end 

    def self.testing 
    return @@edit_methods 
    end 


    view_methods :index, :show 
    edit_methods :new, :create, :edit, :update 
    destroy_methods :destroy 

end 

Les trois méthodes ci-dessus sont différents sur le but, juste pour vous montrer ce que je l'ai essayé. Le troisième fonctionne, mais renvoie les mêmes résultats, peu importe le contrôleur que je teste. Probablement parce que les variables de classe sont stockées dans le contrôleur d'application donc sont modifiées globalement.

Toute aide serait grandement appréciée.

Répondre

3

Le problème est que vos variables de classe sont héritées, mais pointent vers la même instance de Array. Si vous mettez à jour un, il sera également mis à jour sur toutes les classes qui ont hérité du Array.

ActiveSupport offre un solution à ce problème en étendant la classe Class avec plusieurs méthodes pour définir attributs de classe héritable. Ils sont utilisés partout en interne dans Rails. Un exemple:

class ApplicationController 
    class_inheritable_array :view_method_list 
    self.view_method_list = [] 

    def self.view_methods(*view_methods) 
    self.view_method_list = view_methods # view_methods are added 
    end 

    view_methods :index, :show 
end 

Maintenant, vous pouvez définir des valeurs par défaut dans ApplicationController et les remplacer plus tard.

class MyController < ApplicationController 
    view_method :my_method 
end 

ApplicationController.view_method_list #=> [:index, :show] 
MyController.view_method_list #=> [:index, :show, :my_method] 

On peut même utiliser la view_method_list comme une instance procédé sur les contrôleurs (par exemple MyController.new.view_method_list).

Dans votre exemple, vous n'avez pas défini un moyen de supprimer des méthodes des listes, mais l'idée est de faire quelque chose comme ce qui suit (en cas de besoin):

# given the code above... 
class MyController 
    self.view_method_list.delete :show 
end 
MyController.view_method_list #=> [:index, :my_method] 
+0

Wow! C'est exactement ce que je cherchais. Merci beaucoup pour cette information. J'espère que cela aide les autres aussi. C'est difficile à chercher, je suis content que vous y ayez répondu :) –

0

Je l'ai tourné en un plugin comme ça:

module ThreatLevel 

    def self.included(base) 
    base.send :extend, ClassMethods 
    end 

    module ClassMethods 
    def roger_that! 
     class_inheritable_array :view_method_list, :edit_method_list, :destroy_method_list 

     self.view_method_list = Array.new 
     self.edit_method_list = Array.new 
     self.destroy_method_list = Array.new 

     def self.view_methods(*view_methods) 
     self.view_method_list = view_methods 
     end 

     def self.edit_methods(*edit_methods) 
     self.edit_method_list = edit_methods 
     end 

     def self.destroy_methods(*destroy_methods) 
     self.destroy_method_list = destroy_methods 
     end 

     view_methods :index, :show 
     edit_methods :new, :create, :edit, :update 
     destroy_methods :destroy 
    end 
    end 
end 

ActionController::Base.send :include, ThreatLevel 

Appel à roger_that! sur le super_controller où vous voulez qu'il prenne effet le tour.

Questions connexes