2011-07-19 20 views
77

en aşağıdaki karma var diyelim: ...Yakut metaprogramming: Dinamik örnek değişken adları

{ :foo => 'bar', :baz => 'qux' } 

Dinamik bir nesne içinde örnek değişkenler olmak anahtarlarını ve değerlerini ayarlayabilirsiniz nasıl

class Example 
    def initialize(hash) 
    ... magic happens here... 
    end 
end 

... Ben

@foo = 'bar' 
@baz = 'qux' 

... modeli içinde aşağıdaki ile bitirmek böylece?

cevap

145

Aradığınız yöntem instance_variable_set. Yani:

hash.each { |name, value| instance_variable_set(name, value) } 

Ya da daha kısa bir süre,

hash.each &method(:instance_variable_set) 

sizin örnek değişken adları "@" (bunlar OP'ın örnekte olduğu gibi), bunları eklemeniz gerekir eksikse

, bu yüzden daha fazla gibi olacaktır:

hash.each { |name, value| instance_variable_set("@#{name}", value) } 
+1

Mükemmel, teşekkürler! – Andrew

+15

1.9.3 için benim için çalışmadı. Bunu yerine kullanıyorum hash.each {| k, v | instance_variable_set ("@ # {k}", v)} ' – Andrei

+0

Sooo, bu harika! (: Instance_variable_set) 'ihtiyacı iki parametre alır instance_variable_set' yöntemle' Ruby –

12
h = { :foo => 'bar', :baz => 'qux' } 

o = Struct.new(*h.keys).new(*h.values) 

o.baz 
=> "qux" 
o.foo 
=> "bar" 
+1

Bu oldukça ilginç ... ikinci zincirleme tam olarak nedir? .new() 'ne yapıyor? – Andrew

+2

@Andrew: 'Struct.new', hash tuşlarına dayalı yeni bir sınıf oluşturur ve sonra ikinci 'new', yeni oluşturulan sınıfın ilk nesnesini oluşturur ve Hash'ın değerlerine başlatabilir. Bkz. Http://www.ruby-doc.org/core-1.8.7/classes/Struct.html – DigitalRoss

+2

Bunu yapmak gerçekten çok iyi bir yoldur, çünkü bu, Yapımın ne için yapıldığıdır. – Chuck

4

Ayrıca varolmayan bir örneğini ayarından engeller send kullanabilirsiniz değişkenleri:

def initialize(hash) 
    hash.each { |key, value| send("#{key}=", value) } 
end 

kullanın send Sınıfındaki varken senin örnek değişkenleri için attr_accessor gibi bir pasör:

class Example 
    attr_accessor :foo, :baz 
    def initialize(hash) 
    hash.each { |key, value| send("#{key}=", value) } 
    end 
end