Erubis Users' Guide
2 Tutorial
2-1 Basic Example
Here is a basic example of Erubis.
<ul> <% for item in list %> <li><%= item %></li> <% end %> <%# here is ignored because starting with '#' %> </ul>
require 'erubis'
input = File.read('example1.eruby')
eruby = Erubis::Eruby.new(input) # create Eruby object
puts "---------- script source ---"
puts eruby.src # print script source
puts "---------- result ----------"
list = ['aaa', 'bbb', 'ccc']
puts eruby.result(binding()) # get result
## or puts eruby.result(:list=>list) # or pass Hash instead of Binding
## # or
## eruby = Erubis::Eruby.new
## input = File.read('example1.eruby')
## src = eruby.convert(input)
## eval src
$ ruby example1.rb ---------- script source --- _buf = ''; _buf << '<ul> '; for item in list _buf << ' <li>'; _buf << ( item ).to_s; _buf << '</li> '; end _buf << '</ul> '; _buf.to_s ---------- result ---------- <ul> <li>aaa</li> <li>bbb</li> <li>ccc</li> </ul>
Erubis has command 'erubis'. Command-line option '-x' shows the compiled source code of eRuby script.
$ erubis -x example1.eruby _buf = ''; _buf << '<ul> '; for item in list _buf << ' <li>'; _buf << ( item ).to_s; _buf << '</li> '; end _buf << '</ul> '; _buf.to_s
2-2 Trimming Spaces
Erubis deletes spaces around '<% %>' automatically, while it leaves spaces around '<%= %>'.
<ul>
<% for item in list %> # trimmed
<li>
<%= item %> # not trimmed
</li>
<% end %> # trimmed
</ul>
$ erubis -x example2.eruby
_buf = ''; _buf << '<ul>
'; for item in list
_buf << ' <li>
'; _buf << ( item ).to_s; _buf << '
'; _buf << ' </li>
'; end
_buf << '</ul>
';
_buf.to_s
If you want leave spaces around '<% %>', add command-line property '--trim=false'.
$ erubis -x --trim=false example2.eruby
_buf = ''; _buf << '<ul>
'; _buf << ' '; for item in list ; _buf << '
'; _buf << ' <li>
'; _buf << ( item ).to_s; _buf << '
'; _buf << ' </li>
'; _buf << ' '; end ; _buf << '
'; _buf << '</ul>
';
_buf.to_s
Or add option :trim=>false to Erubis::Eruby.new().
require 'erubis'
input = File.read('example2.eruby')
eruby = Erubis::Eruby.new(input, :trim=>false)
puts "----- script source ---"
puts eruby.src # print script source
puts "----- result ----------"
list = ['aaa', 'bbb', 'ccc']
puts eruby.result(binding()) # get result
$ ruby example2.rb
----- script source ---
_buf = ''; _buf << '<ul>
'; _buf << ' '; for item in list ; _buf << '
'; _buf << ' <li>
'; _buf << ( item ).to_s; _buf << '
'; _buf << ' </li>
'; _buf << ' '; end ; _buf << '
'; _buf << '</ul>
';
_buf.to_s
----- result ----------
<ul>
<li>
aaa
</li>
<li>
bbb
</li>
<li>
ccc
</li>
</ul>
2-3 Escape
Erubis has ability to escape (sanitize) expression. Erubis::Eruby class act as the following:
<%= expr %>- not escaped.<%== expr %>- escaped.<%=== expr %>- out to $stderr.<%==== expr %>- ignored.
Erubis::EscapedEruby(*1) class handle '<%= %>' as escaped and '<%== %>' as not escaped. It means that using Erubis::EscapedEruby you can escape expression by default. Also Erubis::XmlEruby class (which is equivalent to Erubis::EscapedEruby) is provided for compatibility with Erubis 1.1.
<% for item in list %> <p><%= item %></p> <p><%== item %></p> <p><%=== item %></p> <% end %>
require 'erubis'
input = File.read('example3.eruby')
eruby = Erubis::EscapedEruby.new(input) # or Erubis::XmlEruby
puts "----- script source ---"
puts eruby.src # print script source
puts "----- result ----------"
list = ['<aaa>', 'b&b', '"ccc"']
puts eruby.result(binding()) # get result
$ ruby example3.rb 2> stderr.log
----- script source ---
_buf = ''; for item in list
_buf << ' <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
<p>'; _buf << ( item ).to_s; _buf << '</p>
<p>'; $stderr.puts("*** debug: item=#{(item).inspect}"); _buf << '</p>
'; end
_buf.to_s
----- result ----------
<p><aaa></p>
<p><aaa></p>
<p></p>
<p>b&b</p>
<p>b&b</p>
<p></p>
<p>"ccc"</p>
<p>"ccc"</p>
<p></p>
$ cat stderr.log
*** debug: item="<aaa>"
*** debug: item="b&b"
*** debug: item="\"ccc\""
The command-line option '-e' will do the same action as Erubis::EscapedEruby. This option is available for any language.
$ erubis -l ruby -e example3.eruby
_buf = ''; for item in list
_buf << ' <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
<p>'; _buf << ( item ).to_s; _buf << '</p>
<p>'; $stderr.puts("*** debug: item=#{(item).inspect}"); _buf << '</p>
'; end
_buf.to_s
Escaping function (default 'Erubis::XmlHelper.escape_xml()') can be changed by command-line property '--escapefunc=xxx' or by overriding Erubis::Eruby#escaped_expr() in subclass.
class CGIEruby < Erubis::Eruby
def escaped_expr(code)
return "CGI.escapeHTML((#{code.strip}).to_s)"
#return "h(#{code.strip})"
end
end
class LatexEruby < Erubi::Eruby
def escaped_expr(code)
return "(#{code}).gsub(/[%\\]/,'\\\\\&')"
end
end
- (*1)
- Erubis::EscapedEruby class includes Erubis::EscapeEnhancer which swtches the action of '<%= %>' and '<%== %>'.
2-4 Embedded Pattern
You can change embedded pattern '<% %>' to another by command-line option '-p' or option ':pattern=>...' of Erubis::Eruby.new().
<!--% for item in list %--> <p><!--%= item %--></p> <!--% end %-->
$ erubis -x -p '<!--% %-->' example4.eruby _buf = ''; for item in list _buf << ' <p>'; _buf << ( item ).to_s; _buf << '</p> '; end _buf.to_s
require 'erubis'
input = File.read('example4.eruby')
eruby = Erubis::Eruby.new(input, :pattern=>'<!--% %-->')
# or '<(?:!--)?% %(?:--)?>'
puts "---------- script source ---"
puts eruby.src # print script source
puts "---------- result ----------"
list = ['aaa', 'bbb', 'ccc']
puts eruby.result(binding()) # get result
$ ruby example4.rb ---------- script source --- _buf = ''; for item in list _buf << ' <p>'; _buf << ( item ).to_s; _buf << '</p> '; end _buf.to_s ---------- result ---------- <p>aaa</p> <p>bbb</p> <p>ccc</p>
It is able to specify regular expression with :pattern option.
Notice that you must use '(?: )' instead of '( )' for grouping.
For example, '<(!--)?% %(--)?>' will not work while '<(?:!--)?% %(?:--)?>' will work.
2-5 Context Object
Context object is a set of data which are used in eRuby script. Using context object makes clear which data to be used. In Erubis, Hash object and Erubis::Context object are available as context object.
Context data can be accessible via instance variables in eRuby script.
<span><%= @val %></span> <ul> <% for item in @list %> <li><%= item %></li> <% end %> </ul>
require 'erubis'
input = File.read('example5.eruby')
eruby = Erubis::Eruby.new(input) # create Eruby object
## create context object
## (key means var name, which may be string or symbol.)
context = {
:val => 'Erubis Example',
'list' => ['aaa', 'bbb', 'ccc'],
}
## or
# context = Erubis::Context.new()
# context['val'] = 'Erubis Example'
# context[:list] = ['aaa', 'bbb', 'ccc'],
puts eruby.evaluate(context) # get result
$ ruby example5.rb <span>Erubis Example</span> <ul> <li>aaa</li> <li>bbb</li> <li>ccc</li> </ul>
The difference between Erubis#result(binding) and Erubis#evaluate(context) is that the former invokes 'eval @src, binding' and the latter invokes 'context.instance_eval @src'. This means that data is passed into eRuby script via local variables when Eruby::binding() is called, or passed via instance variables when Eruby::evaluate() is called.
Here is the definition of Erubis#result() and Erubis#evaluate().
def result(_binding=TOPLEVEL_BINDING)
if _binding.is_a?(Hash)
# load hash data as local variable
_h = _binding
_binding = binding()
eval _h.collect{|k,v| "#{k} = _h[#{k.inspect}];"}.join, _binding
end
return eval(@src, _binding)
end
def evaluate(_context=Erubis::Context.new)
if _context.is_a?(Hash)
# convert hash object to Context object
_hash = _context
_context = Erubis::Context.new
_hash.each {|k, v| _context[k] = v }
end
return _context.instance_eval(@src)
end
instance_eval() is defined at Object class so it is able to use any object as a context object as well as Hash or Erubis::Context.
class MyData
attr_accessor :val, :list
end
## any object can be a context object
mydata = MyData.new
mydata.val = 'Erubis Example'
mydata.list = ['aaa', 'bbb', 'ccc']
require 'erubis'
eruby = Erubis::Eruby.new(File.read('example5.eruby'))
puts eruby.evaluate(mydata)
$ ruby example6.rb <span>Erubis Example</span> <ul> <li>aaa</li> <li>bbb</li> <li>ccc</li> </ul>
It is recommended to use 'Erubis::Eruby#evaluate(context)' rather than 'Erubis::Eruby#result(binding())' because the latter has some problems. See evaluate(context) v.s. result(binding) section for details.
2-6 Context Data File
Command-line option '-f' specifies context data file. Erubis load context data file and use it as context data. Context data file can be YAML file ('*.yaml' or '*.yml') or Ruby script ('*.rb').
<h1><%= @title %></h1>
<ul>
<% for user in @users %>
<li>
<a href="mailto:<%= user['mail']%>"><%= user['name'] %></a>
</li>
<% end %>
</ul>
title: Users List
users:
- name: foo
mail: foo@mail.com
- name: bar
mail: bar@mail.net
- name: baz
mail: baz@mail.org
@title = 'Users List'
@users = [
{ 'name'=>'foo', 'mail'=>'foo@mail.com' },
{ 'name'=>'bar', 'mail'=>'bar@mail.net' },
{ 'name'=>'baz', 'mail'=>'baz@mail.org' },
]
$ erubis -f context.yaml example7.eruby
<h1>Users List</h1>
<ul>
<li>
<a href="mailto:foo@mail.com">foo</a>
</li>
<li>
<a href="mailto:bar@mail.net">bar</a>
</li>
<li>
<a href="mailto:baz@mail.org">baz</a>
</li>
</ul>
$ erubis -f context.rb example7.eruby
<h1>Users List</h1>
<ul>
<li>
<a href="mailto:foo@mail.com">foo</a>
</li>
<li>
<a href="mailto:bar@mail.net">bar</a>
</li>
<li>
<a href="mailto:baz@mail.org">baz</a>
</li>
</ul>
Command-line option '-S' converts keys of mapping in YAML data file from string into symbol. Command-line option '-B' invokes 'Erubis::Eruby#result(binding())' instead of 'Erubis::Eruby#evaluate(context)'.
2-7 Context Data String
Command-line option '-c str' enables you to specify context data in command-line. str can be YAML flow-style or Ruby code.
<h1><%= @title %></h1> <ul> <% for item in @list %> <li><%= item %></li> <% end %> </ul>
$ erubis -c '{title: Example, list: [AAA, BBB, CCC]}' example8.eruby
<h1>Example</h1>
<ul>
<li>AAA</li>
<li>BBB</li>
<li>CCC</li>
</ul>
$ erubis -c '@title="Example"; @list=%w[AAA BBB CCC]' example8.eruby <h1>Example</h1> <ul> <li>AAA</li> <li>BBB</li> <li>CCC</li> </ul>
2-8 Preamble and Postamble
The first line ('_buf = '';') in the compiled source code is called preamble and the last line ('_buf.to_s') is called postamble.
Command-line option '-b' skips the output of preamble and postamble.
<% for item in @list %> <b><%= item %></b> <% end %>
$ erubis -x example9.eruby _buf = ''; for item in @list _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b> '; end _buf.to_s $ erubis -x -b example9.eruby for item in @list _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b> '; end
Erubis::Eruby.new option ':preamble=>false' and ':postamble=>false' also suppress output of preamble or postamle.
require 'erubis'
input = File.read('example9.eruby')
eruby1 = Erubis::Eruby.new(input)
eruby2 = Erubis::Eruby.new(input, :preamble=>false, :postamble=>false)
puts eruby1.src # print preamble and postamble
puts "--------------"
puts eruby2.src # don't print preamble and postamble
$ ruby example9.rb _buf = ''; for item in @list _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b> '; end _buf.to_s -------------- for item in @list _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b> '; end
2-9 Processing Instruction (PI) Converter
Erubis can parse Processing Instructions (PI) as embedded pattern.
- '
<?rb ... ?>' represents Ruby statement. - '
@{...}@' represents escaped expression value. - '
@!{...}@' represents normal expression value. - '
@!!{...}@' prints expression value to standard output. - (experimental) '
<%= ... %>' is also available to print expression value.
This is more useful than basic embedded pattern ('<% ... >') because PI doesn't break XML or HTML at all.
For example the following XHTML file is well-formed and HTML validator got no errors on this example.
<?xml version="1.0" ?>
<?rb
lang = 'en'
list = ['<aaa>', 'b&b', '"ccc"']
?>
<html lang="@!{lang}@">
<body>
<ul>
<?rb for item in list ?>
<li>@{item}@</li>
<?rb end ?>
</ul>
</body>
</html>
If the command-line property '--pi=name' is specified, erubis command parses input with PI converter. If name is omitted then the following name is used according to '-l lang'.
| '-l' option | PI name |
|---|---|
| -l ruby | <?rb ... ?> |
| -l php | <?php ... ?> |
| -l perl | <?perl ... ?> |
| -l java | <?java ... ?> |
| -l javascript | <?js ... ?> |
| -l scheme | <?scheme ... ?> |
$ erubis -x --pi example10.xhtml _buf = ''; _buf << '<?xml version="1.0" ?> '; lang = 'en' list = ['<aaa>', 'b&b', '"ccc"'] _buf << '<html lang="'; _buf << (lang).to_s; _buf << '"> <body> <ul> '; for item in list _buf << ' <li>'; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '</li> '; end _buf << ' </ul> </body> </html> '; _buf.to_s
Expression character can be changeable by command-line property '--embchar=char. Default is '@'.
Use Erubis::PI::Eruby instead of Erubis::Eruby if you want to use PI as embedded pattern.
require 'erubis'
input = File.read('example10.xhtml')
eruby = Erubis::PI::Eruby.new(input)
print eruby.src
$ ruby example10.rb _buf = ''; _buf << '<?xml version="1.0" ?> '; lang = 'en' list = ['<aaa>', 'b&b', '"ccc"'] _buf << '<html lang="'; _buf << (lang).to_s; _buf << '"> <body> <ul> '; for item in list _buf << ' <li>'; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '</li> '; end _buf << ' </ul> </body> </html> '; _buf.to_s
(experimental) Erubis supports '<%= ... %>' pattern with PI pattern.
<table>
<tr>
<?rb for item in @list ?>
<td>@{item.id}@</td>
<td>@{item.name}@</td>
<td>
<%= link_to 'Destroy', {:action=>'destroy', :id=>item.id},
:confirm=>'Are you OK?' %>
</td>
<?rb end ?>
</tr>
</table>
2-10 Retrieve Ruby Code
Similar to '-x', ommand-line option '-X' shows converted Ruby source code. The difference between '-x' and 'X' is that the former converts text part but the latter ignores it. It means that you can retrieve Ruby code from eRuby script by '-X' option.
For example, see the following eRuby script. This is some complex, so it is difficult to grasp the program code.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<body>
<h3>List</h3>
<% if @list.nil? || @list.empty? %>
<p>not found.</p>
<% else %>
<table>
<tbody>
<% @list.each_with_index do |item, i| %>
<tr bgcolor="<%= i % 2 == 0 ? '#FCC' : '#CCF' %>">
<td><%= item %></td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
</body>
</html>
Command-line option '-X' extracts only the ruby code from eRuby script.
$ erubis -X example11.rhtml
_buf = '';
if @list.nil? || @list.empty?
else
@list.each_with_index do |item, i|
_buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
_buf << ( item ).to_s;
end
end
_buf.to_s
Command-line option '-C' (cmpact) deletes empty lines.
$ erubis -XC example11.rhtml
_buf = '';
if @list.nil? || @list.empty?
else
@list.each_with_index do |item, i|
_buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
_buf << ( item ).to_s;
end
end
_buf.to_s
Option '-U' (unique) converts empty lines into a line.
$ erubis -XU example11.rhtml
_buf = '';
if @list.nil? || @list.empty?
else
@list.each_with_index do |item, i|
_buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
_buf << ( item ).to_s;
end
end
_buf.to_s
Option '-N' (number) adds line number. It is available with '-C' or '-U'.
$ erubis -XNU example11.rhtml
1: _buf = '';
7: if @list.nil? || @list.empty?
9: else
12: @list.each_with_index do |item, i|
13: _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
14: _buf << ( item ).to_s;
16: end
19: end
22: _buf.to_s
Command-line option '-X' is available with PHP script.
<?xml version="1.0"?>
<html>
<body>
<h3>List</h3>
<?php if (!$list) { ?>
<p>not found.</p>
<?php } else { ?>
<table>
<tbody>
<?php $i = 0; ?>
<?php foreach ($list as $item) { ?>
<tr bgcolor="<?php echo ++$i % 2 == 1 ? '#FCC' : '#CCF'; ?>">
<td><?php echo $item; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
<?php } ?>
</body>
</html>
$ erubis -XNU -l php --pi=php --trim=false example11.php
5: <?php if (!$list) { ?>
7: <?php } else { ?>
10: <?php $i = 0; ?>
11: <?php foreach ($list as $item) { ?>
12: <?php echo ++$i % 2 == 1 ? '#FCC' : '#CCF'; ?>
13: <?php echo $item; ?>
15: <?php } ?>
18: <?php } ?>