ruby - रूबी टेम्पलेट्स: इनलाइन ईआरबी में चर कैसे पास करें?



templates syntax (6)

एक साधारण समाधान के लिए, OpenStruct उपयोग OpenStruct :

require 'erb'
require 'ostruct'
namespace = OpenStruct.new(name: 'Joan', last: 'Maragall')
template = 'Name: <%= name %> <%= last %>'
result = ERB.new(template).result(namespace.instance_eval { binding })
#=> Name: Joan Maragall

उपर्युक्त कोड काफी सरल है लेकिन कम से कम दो समस्याएं हैं: 1) चूंकि यह OpenStruct पर निर्भर करता है, OpenStruct एक गैर-मौजूदा परिवर्तनीय रिटर्न nil पहुंच होती है जबकि आप शायद यह पसंद करते हैं कि यह शोर में विफल रहा है। 2) binding को एक ब्लॉक के भीतर बुलाया जाता है, यह एक बंद में है, इसलिए इसमें दायरे में सभी स्थानीय चर शामिल हैं (वास्तव में, ये चर संरचना के गुणों को छाया करेंगे!)।

तो यहां एक और समाधान है, अधिक verbose लेकिन इनमें से किसी भी समस्या के बिना:

class Namespace
  def initialize(hash)
    hash.each do |key, value|
      singleton_class.send(:define_method, key) { value }
    end 
  end

  def get_binding
    binding
  end
end

template = 'Name: <%= name %> <%= last %>'
ns = Namespace.new(name: 'Joan', last: 'Maragall')
ERB.new(template).result(ns.get_binding)
#=> Name: Joan Maragall

बेशक, यदि आप अक्सर इसका उपयोग करने जा रहे हैं, तो सुनिश्चित करें कि आप एक String#erb एक्सटेंशन बनाते हैं जो आपको "x=<%= x %>, y=<%= y %>".erb(x: 1, y: 2) लिखने की अनुमति देता है "x=<%= x %>, y=<%= y %>".erb(x: 1, y: 2)

मेरे पास रूबी कोड में एक ईआरबी टेम्पलेट है:

require 'erb'

DATA = {
    :a => "HELLO",
    :b => "WORLD",
}

template = ERB.new <<-EOF
    current key is: <%= current %>
    current value is: <%= DATA[current] %>
EOF

DATA.keys.each do |current|
    result = template.result
    outputFile = File.new(current.to_s,File::CREAT|File::TRUNC|File::RDWR)
    outputFile.write(result)
    outputFile.close
end

मैं टेम्पलेट में परिवर्तनीय "वर्तमान" पास नहीं कर सकता।

त्रुटि है:

(erb):1: undefined local variable or method `current' for main:Object (NameError)

मैं यह कैसे तय करुं?


Answer #1

जैसा कि अन्य ने कहा, चर के कुछ सेट के साथ ईआरबी का मूल्यांकन करने के लिए, आपको उचित बाध्यकारी की आवश्यकता है। कक्षाओं और विधियों को परिभाषित करने के साथ कुछ समाधान हैं लेकिन मुझे लगता है कि सबसे सरल और सबसे अधिक नियंत्रण और सुरक्षित देना स्वच्छ बाध्यकारी उत्पन्न करना और ईआरबी को पार्स करने के लिए इसका उपयोग करना है। यहां मेरा लेना है (रूबी 2.2.x):

module B
  def self.clean_binding
    binding
  end

  def self.binding_from_hash(**vars)
    b = self.clean_binding
    vars.each do |k, v|
      b.local_variable_set k.to_sym, v
    end
    return b
  end
end
my_nice_binding = B.binding_from_hash(a: 5, **other_opts)
result = ERB.new(template).result(my_nice_binding)

मुझे लगता है कि eval और बिना ** साथ 2.1 से पुराने रूबी के साथ काम किया जा सकता है


Answer #2

मैं आपको यह बहुत अच्छा जवाब नहीं दे सकता कि यह क्यों हो रहा है क्योंकि मुझे 100% यकीन नहीं है कि ईआरबी कैसे काम करता है, लेकिन केवल ईआरबी आरडीओक्स को देखकर , यह कहता है कि आपको binding आवश्यकता है जो a Binding or Proc object which is used to set the context of code evaluation. अपने उपरोक्त कोड को दोबारा कोशिश कर रहा है और result = template.result को बदलकर result = template.result(binding) ने इसे काम किया है।

मुझे यकीन है कि उम्मीद है कि कोई यहां कूद जाएगा और क्या हो रहा है इसके बारे में अधिक विस्तृत स्पष्टीकरण प्रदान करेगा। चीयर्स।

संपादित करें: Binding पर कुछ और जानकारी के लिए और यह सब थोड़ा स्पष्ट (कम से कम मेरे लिए) बनाने के लिए, बाइंडिंग आरडीओसी देखें



Answer #4

Binding का उपयोग कर सरल समाधान:

b = binding
b.local_variable_set(:a, 'a')
b.local_variable_set(:b, 'b')
ERB.new(template).result(b)

Answer #5

संपादित करें : यह एक गंदे कामकाज है। कृपया मेरा दूसरा जवाब देखें।

यह पूरी तरह अजीब है, लेकिन जोड़ रहा है

current = ""

"प्रत्येक के लिए" लूप समस्या से हल करने से पहले।

भगवान स्क्रिप्टिंग भाषाओं और उनकी "भाषा विशेषताओं" को आशीर्वाद देते हैं ...





erb