Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby templates: How to pass variables into inlined ERB?

I have an ERB template inlined into Ruby code:

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 

I can't pass the variable "current" into the template.

The error is:

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

How do I fix this?

like image 856
ivan_ivanovich_ivanoff Avatar asked Aug 27 '09 05:08

ivan_ivanovich_ivanoff


People also ask

What does ERB do in Ruby?

ERB (or Ruby code generated by ERB ) returns a string in the same character encoding as the input string. When the input string has a magic comment, however, it returns a string in the encoding specified by the magic comment.

What is ERB templating?

An ERB template looks like a plain-text document interspersed with tags containing Ruby code. When evaluated, this tagged code can modify text in the template. Puppet passes data to templates via special objects and variables, which you can use in the tagged Ruby code to control the templates' output.

What is ERB in Ruby on Rails?

ERB is a templating engine. A templating engine allows you to mix HTML & Ruby so you can generate web pages using data from your database. ERB is Rails default engine for rendering views. Note: Rails uses an implementation called erubi instead of the ERB class from the Ruby standard library.

What is a .ERB file?

Script written in ERB, a templating language for Ruby; may include any type of plain text or source code, but also includes Ruby ERB code that generates additional text into the resulting file when run with the ERB template engine. ERB is often used for templating Web files such as . RB, . RHTML, .


1 Answers

For a simple solution, use 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 

The code above is simple enough but has (at least) two problems: 1) Since it relies on OpenStruct, an access to a non-existing variable returns nil while you'd probably prefer that it failed noisily. 2) binding is called within a block, that's it, in a closure, so it includes all the local variables in the scope (in fact, these variables will shadow the attributes of the struct!).

So here is another solution, more verbose but without any of these problems:

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 

Of course, if you are going to use this often, make sure you create a String#erb extension that allows you to write something like "x=<%= x %>, y=<%= y %>".erb(x: 1, y: 2).

like image 145
12 revs Avatar answered Sep 28 '22 23:09

12 revs