रूबी मेटाप्रोग्रामिंग: डायनेमिक उदाहरण चर नाम


94

मान लीजिए कि मेरे पास निम्नलिखित हैश है:

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

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

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

... ताकि मैं मॉडल के अंदर निम्नलिखित के साथ समाप्त हो ...

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

?

जवाबों:


168

जिस विधि की आपको तलाश है 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) }

18
1.9.3 के लिए मेरे लिए काम नहीं किया। मैंने इसके बजाय इसका इस्तेमाल कियाhash.each {|k,v| instance_variable_set("@#{k}",v)}
आंद्रेई

3
रूबी से प्यार करने का एक और कारण है
jschorr

क्या आप कृपया बता सकते हैं कि कैसे hash.each &method(:instance_variable_set), विधि instance_variable_setको दो मापदंडों की आवश्यकता है जो इसे चाहिए?
अर्नोल्ड रोआ

किसी भी विचार यह कैसे पुनरावर्ती करने के लिए? (यदि इनपुट हैश में कई स्तर हैं)
nemenems

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

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

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

1
यह बहुत दिलचस्प है ... वास्तव में दूसरा जंजीर .new()क्या कर रहा है?
एंड्रयू

3
@Andrew: Struct.newहैश कीज़ के आधार पर एक नया वर्ग बनाता है, और फिर दूसरा हैश new-निर्मित वर्ग की पहली वस्तु बनाता है, इसे हैश के मानों से आरंभ करता है। रूबी- doc.org/core-1.8.7/classes/Struct.html
DigitalRoss

2
यह वास्तव में यह करने के लिए एक बहुत अच्छा तरीका है क्योंकि यह बहुत ज्यादा है जो संरचना के लिए बनाया गया है।
चक

2
या OpenStruct का उपयोग करेंrequire 'ostruct'; h = {:foo => 'foo'}; o = OpenStruct.new(h); o.foo == 'foo'
जस्टिन फोर्स

मुझे अपनी चाबियों को प्रतीकों के लिए मैप करना था:Struct.new(*hash.keys.map { |str| str.to_sym }).new(*hash.values)
मिटाया

7

आप हमें रोना चाहते हैं :)

किसी भी मामले में, देखें Object#instance_variable_getऔर Object#instance_variable_set

खुश कोडिंग।


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

उदाहरण के लिए, मैं set_entityसभी नियंत्रकों के लिए एक सामान्य कॉलबैक चाहता हूं, और मैं मौजूदा उदाहरण चर के साथ हस्तक्षेप नहीं करना चाहता हूंdef set_entity(name, model); instance_variable_set(name, model.find_by(params[:id])); end;
user1201917

5

आप उपयोग भी कर सकते हैं 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.