2009-06-04 10 views
1

J'essaie de SECHER un peu mon code de sorte que j'écris une méthode pour reporter ou déléguer certaines méthodes à un objet différent, mais seulement s'il existe. Voici l'idée de base: J'ai Shipment < AbstractShipment qui pourrait avoir un Reroute < AbstractShipment. Un Shipment ou Reroute peut avoir un Delivery (ou des livraisons), mais pas les deux. Lorsque j'appelle expédition.deliveries, je veux vérifier si elle a d'abord un réacheminement. Si ce n'est pas le cas, appelez simplement AbstractShipment méthode deliveries; Si c'est le cas, déléguez la méthode à la redirection.Appel de super à partir d'une méthode avec alias

J'ai essayé avec le simple code ci-dessous:

module Kernel 
    private 
    def this_method 
     caller[0] =~ /`([^']*)'/ and $1 
    end   
end 

class Shipment < AbstractShipment 
    ... 

    def deferToReroute 
    if self.reroute.present? 
     self.reroute.send(this_method) 
    else 
     super 
    end 
    end 

    alias_method :isComplete?, :deferToReroute 
    alias_method :quantityReceived, :deferToReroute 
    alias_method :receiptDate, :deferToReroute 
end 

Le Kernel.this_method est juste une commodité pour savoir quelle méthode a été appelée. Toutefois, l'appel super lance

super: no superclass method `deferToReroute' 

J'ai cherché un peu et trouvé this link qui explique que ce bogue dans Ruby 1.8, mais est fixé à 1,9. Malheureusement, je ne peux pas encore mettre à jour ce code à 1.9, donc quelqu'un a-t-il des suggestions pour les solutions de contournement?

Merci :-)

Edit: Après un peu de regarder mon code, j'ai réalisé que je ne dois pas vraiment un alias toutes les méthodes que je l'ai fait, je fait seulement besoin Ecrasement la méthode des livraisons puisque les trois autres l'appellent effectivement pour leurs calculs. Cependant, j'aimerais toujours savoir vos pensées depuis que je l'ai déjà rencontré.

Répondre

2

Plutôt que d'utiliser alias_method ici, vous pourriez être mieux servis par dur de ces méthodes, comme si:

class Shipment < AbstractShipment 
    def isComplete? 
    return super unless reroute 
    reroute.isComplete? 
    end 
end 

si vous vous trouvez faites ce 5-10 fois par classe, vous pouvez le faire plus agréable comme ceci:

class Shipment < AbstractShipment 
    def self.deferred_to_reroute(*method_names) 
    method_names.each do |method_name| 
     eval "def #{method_name}; return super unless reroute; reroute.#{method_name}; end" 
    end 
    end 
    deferred_to_reroute :isComplete?, :quantityReceived, :receiptDate 
end 

L'utilisation d'un eval droit offre good performance characteristics et vous permet d'avoir une simple syntaxe déclarative pour ce que vous faites au sein de votre définition de classe.

+0

Génial! Si j'y avais joué un peu plus longtemps, j'aurais essayé quelque chose comme ça depuis que j'ai écrit un plug-in qui fait quelque chose de similaire, mais je doute qu'il aurait été aussi propre. Merci beaucoup :-) –

Questions connexes