2010-05-10 21 views
0

Voici la situation:Remplacer la même méthode de classe dans Ruby avec plusieurs modules, avec nécessité d'appeler super. Est-ce que j'utilise Method Alias, ou un autre truc intelligent?

J'ai un modèle utilisateur, et deux modules pour l'authentification: Oauth et Openid. Les deux remplacent ActiveRecord#save et ont une part équitable de la logique d'implémentation.

Étant donné que je peux dire lorsque l'utilisateur tente de se connecter via OAuth contre OpenID, mais que les deux ont substituée save, comment faire « enfin » passer outre save ce que je peux conditionnellement appeler l'une des implémentations des modules de cela?

Voici la structure de base de ce que je décris:

module UsesOauth 

    def self.included(base) 
    base.class_eval do 
     def save 
     puts "Saving with Oauth!" 
     end 

     def save_with_oauth 
     save 
     end 
    end 
    end 

end 

module UsesOpenid 

    def self.included(base) 
    base.class_eval do 
     def save 
     puts "Saving with OpenID!" 
     end 

     def save_with_openid 
     save 
     end 
    end 
    end 

end 

module Sequencer 

    def save 
    if using_oauth? 
     save_with_oauth 
    elsif using_openid? 
     save_with_openid 
    else 
     super 
    end 
    end 

end 

class User < ActiveRecord::Base 
    include UsesOauth 
    include UsesOpenid 
    include Sequencer 
end 

Je pensais à l'aide alias_method like so, mais devenu trop compliqué, parce que je pourrais avoir 1 ou 2 autres modules similaires. J'ai également essayé d'utiliser ces méthodes save_with_oauth (montré ci-dessus), ce qui fonctionne presque. La seule chose qui manque est que je dois aussi appeler ActiveRecord::Base#save (la méthode super), donc quelque chose comme ceci:

def save_with_oauth 
    # do this and that 
    super.save 
    # the rest 
end 

Mais je ne suis pas autorisé à le faire en rubis.

Des idées pour une solution intelligente à cela?

Est-ce que c'est ce que alias_method_chain ferait? J'ai évité cela parce que les gens semblaient dire que c'était une mauvaise idée.

(Trouver des choses que je vais):

Répondre

2

Oui chaîne méthode alias vous aiderait dans cette situation.

Mais envisagez d'utiliser un modèle de délégué. La méthode de sauvegarde originale déclencherait un rappel sur l'objet délégué spécial (qui peut être aussi nul) et ferait tout ce qui doit être fait lors de la sauvegarde de l'utilisateur.

Aussi il y a un modèle simliar pris en charge directement par l'enregistrement actve appelé Observer, essayez de lire quelque part à ce sujet peut-être que c'est une bonne solution aussi. Je ne dis pas que ces méthodes de chaînage sont fausses, mais il existe des façons plus propres d'obtenir ce que vous voulez.