2011-07-29 3 views
0

comment puis-je faire:avec des blocs

class MyClass 

    tile 'some title' 

    collection do 
    node1 'node1' 
    node2 'node2' 

     another_collection do 
     node1 'node1' 
     node2 'node2' 
     end 
    end 
    end_node 'some text' 

end 

et produire suivants:

MyClass.build #=>{:title=>'some title',:collection=>{:node1=>'node1',:node2=>'node2',:another_collection=>{:node1=>'node1',:node2=>'node2'}},:end_node=>'some text'} 

Ce que je tentais est de rendre DSL simple et construire arbre de hachage. Je suis sûr que cela peut être fait avec method_missing et instance_eval, mais je ne sais pas comment construire cette logique.

Merci pour l'aide

+1

Qu'avez-vous essayé jusqu'à présent? Pour commencer, essayez de gérer uniquement les appels de méthode de premier niveau, c'est-à-dire d'abord l'utilisation sans blocs. –

+0

Mladen, merci pour la réponse .. Il est trivial de créer des premiers nœuds et blocs. juste dans method_missing fusionner hash avec les noms de méthodes ... le problème est de créer des nœuds d'arbre imbriqués profonds ... – alex

Répondre

7

Dans votre method_missing, vous devriez vérifier si un bloc est donné, et, le cas échéant, appelez récursive la principale méthode avec elle:

class HashBuilder 

    def self.build &block 
    hb = HashBuilder.new 
    hb.instance_eval(&block) 
    hb.hash 
    end 

    attr_reader :hash 

    def initialize 
    @hash = {} 
    end 

    def method_missing meth, *args, &block 
    @hash[meth] = block ? HashBuilder.build(&block) : args.first 
    end 
end 

p HashBuilder.build{ 
    a :b 
    c :d 
    e do 
    f :g 
    end 
} 
#=> {:a=>:b, :c=>:d, :e=>{:f=>:g}} 
+1

Merci l'homme. U vraiment m'aider ... – alex

+1

Super réponse - merci! –

+1

Très cool! Je ne m'attendais pas à ce que la réponse soit si courte. –