2009-12-24 4 views
0

Je voudrais écrire ceci:En utilisant define_method pour définir les méthodes globales en dehors d'un module

[:p, :h1, :h3].each do |tag| 
    define_method(tag) { |text| "<#{tag}>#{text}</#{tag}>" } 
end 

Il est juste quelques méthodes simples pour envelopper le texte dans les balises HTML. Je veux être capable d'utiliser ces méthodes dans le reste du script. Malheureusement, la méthode define_method semble fonctionner uniquement à l'intérieur d'un module. Mais si je faisais cela à l'intérieur d'un module, je ne serais pas en mesure d'écrire proprement p "This is a paragraph.", ce serait quelque chose comme HTML::p "This is a paragraph." ce qui serait assez terrible.

Alors, comment définir des méthodes comme celle-ci globalement?

Répondre

3

Je ne connais pas votre situation dans son ensemble, mais vous ne voulez probablement pas vraiment définir des méthodes globales. Si vous ne voulez pas taper HTML::, ajoutez une instruction include HTML au début de votre code.

+0

cela semblait hacky au premier mais je suppose que c'est plutôt propre et ça fonctionne parfaitement. Je vous remercie! –

2

Une bidouille serait de créer la méthode à l'intérieur de l'objet, qui serait alors méthode globale que vous désirez:

class Object 
    def create_method(name, &block) 
    self.class.send(:define_method, name, &block) 
    end 
end 

tag = 'p' 
a = Object.new 
a.create_method(tag.intern) {|v| puts "<#{tag}>#{v}</#{tag}>"} 

send(tag.intern, 'content') # => <p>content</p> 
+0

Ce code ne définit pas de méthodes 'globales', il ne définit que des méthodes sur la classe du récepteur. Dans cet exemple 'a' est une instance d'Object, les méthodes seraient 'globales' mais en général ce n'est pas vrai avec votre code. – horseyguy

+0

Ceci bien sûr ne fonctionne qu'avec la classe Object ... dans laquelle j'ai ajouté la méthode create_method. Juste pour être clair, ce n'est pas un bon style, de mon sentiment personnel, mais juste une façon de répondre à l'intension de la question originale. – bryantsai

5

Si vous avez vraiment besoin de le faire:

[:p, :h1, :h3].each do |tag| 
    Object.send(:define_method, tag) { |text| "<#{tag}>#{text}</#{tag}>" } 
end