2010-01-21 2 views
1

On suppose, je la classe suivante:magique accès Ruby

class MyClass 
    attr_accessor :vars 

    def initialize 
    @vars = [] 
    end 

    def add_var var 
    @vars << var 
    end 

end 

Je veux accéder inners vars comme ceci:

x = MyClass.new('root') 
x.add_var 'test' 
x.add_var 'something' 
x.add_var Myclass.new('google') 
x.google.add_var 'nice' 

puts x.test 
puts x.something 
puts x.google.nice 

D'une manière générale, est-il possible? Quoi/où dois-je creuser?

+1

Vous pouvez toujours aller 'chemin method_missing'. – vava

+1

Jetez également un coup d'oeil à OpenStruct (http://www.ruby-doc.org/core/classes/OpenStruct.html), pas vraiment la syntaxe que vous voulez mais fondamentalement la même chose. – vava

Répondre

4

il fait partie de la bibliothèque standard Ruby, et il est appelé OpenStruct:

#!/usr/bin/ruby1.8 

require 'ostruct' 

x = OpenStruct.new 
x.google = OpenStruct.new 
x.google.nice = 'Nice. Real nice' 
p x.google.nice  # "Nice. Real nice" 

Vous pouvez également initialiser des attributs dans le constructeur:

x = OpenStruct.new(:google=>OpenStruct.new(:nice=>'Nice. Real nice')) 
p x.google.nice # => "Nice. Real nice" 
0

Bien sûr, vous pouvez. C'est exactement ce que, par exemple, this plugin does pour les paramètres de configuration à l'échelle de l'application.

1

Si vous souhaitez implémenter quelque chose comme ceci, vous devriez en savoir plus sur method_missing. Cette méthode est appelée lorsqu'une méthode est introuvable. En utilisant un code intelligent pour trouver le nom de la méthode appelée dans votre @vars et réagir à ce sujet.

C'est probablement la même méthode que celle utilisée par le plugin weppos.

0

vous pouvez le faire avec instance_varibable_set et instance_variable_get:

MyClass.instance_variable_set (: @ var_name, "valeur")

0

Il suffit de définir dynamiquement une nouvelle méthode et ont le retourner l'objet que vous voulez:

class MyClass 
    attr_accessor :vars 
    attr_reader :name 

    def initialize(name) 
     @name = name 
     @vars = [] 
    end 

    def add_var(var) 
     @vars << var 

     if var.instance_of?(MyClass) 
      class << self; self; end.send(:define_method, var.name.to_sym) { 
       var 
      } 
     end 
    end 
end 

x = MyClass.new(:x) 
x.add_var MyClass.new(:google) 
x.google.add_var MyClass.new(:nice) 
x.google.nice.name #=> :nice 
+0

Définir de nouvelles méthodes est une entreprise délicate. Et en supposant que l'exemple du PO est une vision simpliste de la réalité, les choses pourraient être en désordre. – Veger

+0

Je pense aussi que 'method_missing' peut être une douleur, esp. car une implémentation robuste nécessite également de patcher 'respond_to?'. – horseyguy

+0

Vrai, mais il semble plus flexible dans la suppression, le changement de nom, etc., car il dépend directement de '@ vars'. Ainsi, tous les changements sont reflétés immédiatement. – Veger

Questions connexes