2009-01-14 8 views
2

J'ai une classe avec quelques méthodes. C'est supersekret mais j'ai reproduit ce que je peux ici.Quelle est la meilleure stratégie pour obtenir/définir des métadonnées sur les méthodes Ruby à l'exécution?

Class RayGun 
    # flashes red light 
    # requires confirmation 
    # makes "zowowowowowow" sound 
    def stun! 
    # ... 
    end 

    # flashes blue light 
    # does not require confirmation 
    # makes "trrrtrtrtrrtrtrtrtrtrtr" sound 
    def freeze! 
    # ... 
    end 

    # doesn't flash any lights 
    # does not require confirmation 
    # makes Windows startup sound 
    def killoblast! 
    # ... 
    end 
end 

Je veux être en mesure, lors de l'exécution, interroger la classe sur l'une des méthodes et recevoir un comme hachage ou struct si:

{:lights => 'red', :confirmation => false, :sound => 'windows'} 

Quelle est la meilleure façon de le faire? Évidemment, vous pourriez avoir un fichier YAML séparé à côté et mettre en place une convention pour relier les deux, mais idéalement, je veux du code et des métadonnées en un seul endroit.

L'idée la plus prometteuse que je peux venir avec quelque chose comme ceci:

class RayGun 
    cattr_accessor :metadata 
    def self.register_method(hsh) 
    define_method(hsh.name, hsh.block) 
    metadata[hsh[:name]] = hsh 
    end 

    register_method({ 
    :name => 'stun!', 
    :lights => 'red', 
    :confirmation => 'true', 
    :sound => 'zowowo', 
    :block => Proc.new do 
     # code goes here 
    }) 

    # etc. 
end 

Quelqu'un at-il des meilleures idées? Suis-je aboyer un arbre très mauvais?

Répondre

2

J'ai trouvé une autre stratégie qui tourne autour de http://github.com/wycats/thor/tree. Thor vous permet d'écrire des trucs comme ça:

Class RayGun < Thor 
    desc "Flashes red light and makes zowowowowow sound" 
    method_options :confirmation => :required 
    def stun! 
    # ... 
    end 
end 

Il gère cela en utilisant le (sans papier) crochet Module#method_added. Il fonctionne comme ceci:

  1. Appel à Thor#desc et Thor#method_options ensemble des variables exemple @desc, @method_options.

  2. méthode Définir stun! appelle Thor#method_added(meth)

  3. Thor#method_added registres Task.new(meth.to_s, @desc, @method_options) (grosso modo) et Rétablit @desc, @method_options.

  4. Il est maintenant prêt pour la prochaine méthode

Neat!Si bien que je vais accepter ma propre réponse :)

+1

method_added peut être non documenté sur rdoc, mais c'est sur une documentation liée par le site officiel: http://www.ruby-doc.org/docs/ProgrammingRuby /html/ospace.html –

2

Juste un peu beautyfication:

class RayGun 
    cattr_accessor :metadata 
    def self.register_method(name, hsh, &block) 
    define_method(name, block) 
    metadata[name] = hsh 
    end 

    register_method('stun!', 
    :lights => 'red', 
    :confirmation => 'true', 
    :sound => 'zowowo', 
    ) do 
     # code goes here 
    end 

    # etc. 
end 

Vous ne perdez l'accès facile à la fermeture d'origine, mais probablement pas besoin.

Pour répondre à la question, il ne semble pas mal, vous pourriez faire quelque chose d'un peu plus Conventionnel mais probablement assez bon:

class RayGun 
    cattr_accessor :metadata 

    @metadata[:stun!] = {:lights => 'red', 
         :confirmation => 'true', 
         :sound => 'zowowo'} 
    def stun! 
    # ... 
    end 

    # etc. 
end 

Dans le register_method exemple original est public, si vous avez prévu de l'utiliser Ainsi, la seconde option devient moins utile car elle n'assure pas la cohérence.

1

Il existe l'outil YARD qui vous permet d'ajouter des métadonnées aux méthodes. Je suis à peu près sûr que cela ne fait que coller les méta-données dans les fichiers rdoc que vous générez, mais vous pouvez facilement en tirer parti pour obtenir des informations sur l'exécution.

Questions connexes