2011-07-19 14 views
77

चलो कहते हैं कि मैं निम्नलिखित हैश है:रूबी Metaprogramming: गतिशील उदाहरण चर नाम

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

मैं गतिशील रूप से एक वस्तु में उदाहरण चर बनने के लिए कुंजी और मूल्यों सेट कर सकते हैं ...

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

... ताकि मैं मॉडल के अंदर निम्नलिखित ...

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

साथ अंत?

उत्तर

145

जिस विधि को आप ढूंढ रहे हैं वह instance_variable_set है। तो:

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

या, अधिक संक्षेप में,

hash.each &method(:instance_variable_set) 

अपने उदाहरण चर नाम "@" (के रूप में वे ओपी के उदाहरण में हैं), तो आप उन्हें जोड़ने की आवश्यकता होगी याद कर रहे हैं, तो इसलिए यह अधिक की तरह होगा:

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

बिल्कुल सही, धन्यवाद! – Andrew

+15

मेरे लिए 1.9.3 के लिए काम नहीं किया। मैंने इसके बजाय 'हैश.एच {| के, वी | instance_variable_set ("@ # {k}", v)} ' – Andrei

+0

Sooo, यह कमाल है! –

5

आप हम रोना :)

किसी भी मामले में, Object#instance_variable_get और Object#instance_variable_set देखना चाहते हैं।

हैप्पी कोडिंग।

+0

एर हाँ, मैं सोच रहा नहीं मदद कर सकता है ... क्यों? इसका उपयोग करने के लिए एक अच्छा समय कब होगा? –

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

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

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

यह बहुत दिलचस्प है ... दूसरा जंजीर 'नया()' क्या कर रहा है? – Andrew

+2

@Andrew: 'Struct.new' हैश कुंजी के आधार पर एक नई कक्षा बनाता है, और फिर दूसरा 'नया' हश के मानों को प्रारंभ करने के लिए, केवल बनाई गई कक्षा का पहला ऑब्जेक्ट बनाता है। देखें http://www.ruby-doc.org/core-1.8.7/classes/Struct.html – DigitalRoss

+2

यह वास्तव में ऐसा करने का एक बहुत अच्छा तरीका है क्योंकि यह बहुत अधिक है जिसके लिए संरचना बनाई गई है। – Chuck

4

तुम भी send जो न के बराबर उदाहरण स्थापित करने से उपयोगकर्ता को रोकता है उपयोग कर सकते हैं चर:

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

उपयोग send है अपनी कक्षा में जब अपने उदाहरण चर के लिए attr_accessor की तरह एक सेटर:

class Example 
    attr_accessor :foo, :baz 
    def initialize(hash) 
    hash.each { |key, value| send("#{key}=", value) } 
    end 
end 
संबंधित मुद्दे