2010-11-02 16 views
9

In Ruby gibt es eine Möglichkeit, eine Instanzvariable dynamisch zu einer Klasse hinzuzufügen? Zum Beispiel:Dynamisch Klassenattribute mit attr_accessor erstellen

class MyClass 

    def initialize 
    create_attribute("name") 
    end 

    def create_attribute(name) 
    attr_accessor name.to_sym 
    end 

end 

o = MyClass.new 
o.name = "Bob" 
o.name 
+2

Sie kennen 'OpenStruct'? – Reactormonk

Antwort

25

Eine Möglichkeit (es gibt auch andere) ist instance_variable_set und instance_variable_get zu verwenden, wie so:

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

    def create_attr(name) 
     create_method("#{name}=".to_sym) { |val| 
      instance_variable_set("@" + name, val) 
     } 

     create_method(name.to_sym) { 
      instance_variable_get("@" + name) 
     } 
    end 
end 

t = Test.new 
t.create_attr("bob") 
t.bob = "hello" 
puts t.bob 
+1

Ich mag Ihre Lösung, es ist sauber und zeigt Getter und Setter. Vielen Dank! – dhulihan

+1

Wie würdest du das in ein Modul umwandeln, damit du es mit Klassen kombinieren kannst, die diese Funktionalität haben sollen? – ericso

1

vielleicht,

instance_variable_set(name,value) 

ist das, was Ihr wollen!

zB:

class Mclass 
    def show_variables 
    puts self.class.instance_variables 
    end 
end 

Mclass.instance_variable_set(:@test,1) 
o=Mclass.new 
o.show_variables 

Sie wissen, ist die Klasse zu widersprechen.

0

Hergestellt ein Durcheinander von @ ericso Kommentar/Frage in einem anderen Kommentar zu antworten, so ist es hier in einer Antwort - ein Modul, das ich (basierend auf @ ReeseMoore Code) verwende diese & Set-Instanz zu tun Vars, falls erforderlich:

# adds ability to dynamically create instance vars & attr_accessors 
module Attributable 
    def create_method(name, &block) 
    self.class.send(:define_method, name.to_sym, &block) 
    end 

    def create_setter(m) 
    create_method("#{m}=".to_sym) { |v| instance_variable_set("@#{m}", v) } 
    end 

    def create_getter(m) 
    create_method(m.to_sym) { instance_variable_get("@#{m}") } 
    end 

    def set_attr(method, value) 
    create_setter method 
    send "#{method}=".to_sym, value 
    create_getter method 
    end 
end