tenjin 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.txt +54 -0
  3. data/benchmark/bench.rb +502 -0
  4. data/benchmark/bench_context.rb +17 -0
  5. data/benchmark/bench_context.yaml +141 -0
  6. data/benchmark/templates/_footer.html +4 -0
  7. data/benchmark/templates/_header.html +52 -0
  8. data/benchmark/templates/bench_eruby.rhtml +29 -0
  9. data/benchmark/templates/bench_tenjin.rbhtml +29 -0
  10. data/bin/rbtenjin +449 -0
  11. data/doc-api/classes/Tenjin.html +141 -0
  12. data/doc-api/classes/Tenjin/ArrayBufferTemplate.html +270 -0
  13. data/doc-api/classes/Tenjin/BaseContext.html +312 -0
  14. data/doc-api/classes/Tenjin/Context.html +126 -0
  15. data/doc-api/classes/Tenjin/ContextHelper.html +433 -0
  16. data/doc-api/classes/Tenjin/Engine.html +616 -0
  17. data/doc-api/classes/Tenjin/ErubisTemplate.html +166 -0
  18. data/doc-api/classes/Tenjin/HtmlHelper.html +359 -0
  19. data/doc-api/classes/Tenjin/Preprocessor.html +242 -0
  20. data/doc-api/classes/Tenjin/Template.html +916 -0
  21. data/doc-api/created.rid +1 -0
  22. data/doc-api/files/README_txt.html +185 -0
  23. data/doc-api/files/lib/tenjin_rb.html +136 -0
  24. data/doc-api/fr_class_index.html +36 -0
  25. data/doc-api/fr_file_index.html +28 -0
  26. data/doc-api/fr_method_index.html +89 -0
  27. data/doc-api/index.html +24 -0
  28. data/doc-api/rdoc-style.css +208 -0
  29. data/doc/docstyle.css +188 -0
  30. data/doc/examples.html +312 -0
  31. data/doc/faq.html +909 -0
  32. data/doc/users-guide.html +1691 -0
  33. data/lib/tenjin.rb +959 -0
  34. data/setup.rb +1331 -0
  35. data/tenjin.gemspec +58 -0
  36. data/test/assert-text-equal.rb +45 -0
  37. data/test/data/examples/form/create.rbhtml +4 -0
  38. data/test/data/examples/form/form.rbhtml +14 -0
  39. data/test/data/examples/form/layout.rbhtml +8 -0
  40. data/test/data/examples/form/main.rb +9 -0
  41. data/test/data/examples/form/main.result +21 -0
  42. data/test/data/examples/form/update.rbhtml +4 -0
  43. data/test/data/examples/preprocessing/helper.rb +16 -0
  44. data/test/data/examples/preprocessing/main.rb +11 -0
  45. data/test/data/examples/preprocessing/main.result +17 -0
  46. data/test/data/examples/preprocessing/select.rbhtml +15 -0
  47. data/test/data/examples/preprocessing/select_P.result +18 -0
  48. data/test/data/examples/table/table.rb +9 -0
  49. data/test/data/examples/table/table.rbhtml +16 -0
  50. data/test/data/examples/table/table.result +20 -0
  51. data/test/data/examples/table/table_s.result +18 -0
  52. data/test/data/faq/ex1.rbhtml +5 -0
  53. data/test/data/faq/ex10-baselayout.rbhtml +27 -0
  54. data/test/data/faq/ex10-content.rbhtml +12 -0
  55. data/test/data/faq/ex10-customlayout.rbhtml +11 -0
  56. data/test/data/faq/ex10_inherit.result +25 -0
  57. data/test/data/faq/ex11-bench.rb +28 -0
  58. data/test/data/faq/ex11-content.rbhtml +9 -0
  59. data/test/data/faq/ex11-layout1.rbhtml +5 -0
  60. data/test/data/faq/ex11-layout2.rbhtml +6 -0
  61. data/test/data/faq/ex11.rb +5 -0
  62. data/test/data/faq/ex11.rbhtml +8 -0
  63. data/test/data/faq/ex11.source +11 -0
  64. data/test/data/faq/ex11_arraybuffer.result +15 -0
  65. data/test/data/faq/ex1_chksyntax.result +3 -0
  66. data/test/data/faq/ex2-content.rbhtml +3 -0
  67. data/test/data/faq/ex2-layout.rbhtml +11 -0
  68. data/test/data/faq/ex2_removenl.result +19 -0
  69. data/test/data/faq/ex3.rb +4 -0
  70. data/test/data/faq/ex3.rbhtml +1 -0
  71. data/test/data/faq/ex3_escapefunc1.result +2 -0
  72. data/test/data/faq/ex3_escapefunc2.result +2 -0
  73. data/test/data/faq/ex5.rbhtml +7 -0
  74. data/test/data/faq/ex5_template_args.source +9 -0
  75. data/test/data/faq/ex6-content.rhtml +6 -0
  76. data/test/data/faq/ex6-layout.rhtml +6 -0
  77. data/test/data/faq/ex6.rb +10 -0
  78. data/test/data/faq/ex6_eruby.result +12 -0
  79. data/test/data/faq/ex7-expr-pattern.rb +34 -0
  80. data/test/data/faq/ex7-expr-pattern.rbhtml +3 -0
  81. data/test/data/faq/ex7_expr_pattern.result +4 -0
  82. data/test/data/faq/ex8-m18n.rb +77 -0
  83. data/test/data/faq/ex8-m18n.rbhtml +4 -0
  84. data/test/data/faq/ex8_m18n.result +10 -0
  85. data/test/data/faq/ex9-baselayout.rbhtml +8 -0
  86. data/test/data/faq/ex9-content.rbhtml +6 -0
  87. data/test/data/faq/ex9-mylayout.rbhtml +5 -0
  88. data/test/data/faq/ex9_changelayout.result +11 -0
  89. data/test/data/users_guide/content6.rbhtml +3 -0
  90. data/test/data/users_guide/content7.rbhtml +5 -0
  91. data/test/data/users_guide/content8.rbhtml +2 -0
  92. data/test/data/users_guide/contextdata.rb +7 -0
  93. data/test/data/users_guide/datafile.rb +5 -0
  94. data/test/data/users_guide/datafile.yaml +10 -0
  95. data/test/data/users_guide/ex.rbhtml +6 -0
  96. data/test/data/users_guide/ex.result +7 -0
  97. data/test/data/users_guide/ex.script +5 -0
  98. data/test/data/users_guide/ex_script.result +7 -0
  99. data/test/data/users_guide/ex_source.result +8 -0
  100. data/test/data/users_guide/example1.rbhtml +12 -0
  101. data/test/data/users_guide/example1.result +17 -0
  102. data/test/data/users_guide/example10.rbhtml +4 -0
  103. data/test/data/users_guide/example10_template_args.result +6 -0
  104. data/test/data/users_guide/example11.rbhtml +5 -0
  105. data/test/data/users_guide/example11_template_args_result +2 -0
  106. data/test/data/users_guide/example12.rbhtml +12 -0
  107. data/test/data/users_guide/example12_preprocessed.result +10 -0
  108. data/test/data/users_guide/example12_preprocessed_source.result +10 -0
  109. data/test/data/users_guide/example13.rbhtml +6 -0
  110. data/test/data/users_guide/example13_preprocessed.result +2 -0
  111. data/test/data/users_guide/example13_preprocessed_source.result +2 -0
  112. data/test/data/users_guide/example14.rb +32 -0
  113. data/test/data/users_guide/example14.rbhtml +6 -0
  114. data/test/data/users_guide/example14_tmplclass.result +15 -0
  115. data/test/data/users_guide/example15.rb +10 -0
  116. data/test/data/users_guide/example15_escapefunc.result +14 -0
  117. data/test/data/users_guide/example16.rbhtml +4 -0
  118. data/test/data/users_guide/example16a.rb +10 -0
  119. data/test/data/users_guide/example16a.result +4 -0
  120. data/test/data/users_guide/example16b.rb +13 -0
  121. data/test/data/users_guide/example16b.result +4 -0
  122. data/test/data/users_guide/example16c.rb +12 -0
  123. data/test/data/users_guide/example16c.result +4 -0
  124. data/test/data/users_guide/example1_S.result +14 -0
  125. data/test/data/users_guide/example1_SXNC.result +10 -0
  126. data/test/data/users_guide/example1_source.result +14 -0
  127. data/test/data/users_guide/example2.rbhtml +3 -0
  128. data/test/data/users_guide/example2_sb.result2 +9 -0
  129. data/test/data/users_guide/example3.rbhtml +5 -0
  130. data/test/data/users_guide/example3_syntaxcheck.result +2 -0
  131. data/test/data/users_guide/example4.rbhtml +13 -0
  132. data/test/data/users_guide/example4_datafile_rb.result +13 -0
  133. data/test/data/users_guide/example4_yaml.result +13 -0
  134. data/test/data/users_guide/example5.rbhtml +9 -0
  135. data/test/data/users_guide/example5_datastr_rb.result +9 -0
  136. data/test/data/users_guide/example5_datastr_yaml.result +9 -0
  137. data/test/data/users_guide/example6.rbhtml +19 -0
  138. data/test/data/users_guide/example6_layout.result +29 -0
  139. data/test/data/users_guide/example6_nested.result +28 -0
  140. data/test/data/users_guide/example7_layout2.result +13 -0
  141. data/test/data/users_guide/example8_layout3.result +8 -0
  142. data/test/data/users_guide/example9.rbhtml +18 -0
  143. data/test/data/users_guide/example9_capture.result +26 -0
  144. data/test/data/users_guide/footer.html +5 -0
  145. data/test/data/users_guide/footer.rbhtml +4 -0
  146. data/test/data/users_guide/layout6.rbhtml +17 -0
  147. data/test/data/users_guide/layout7.rbhtml +9 -0
  148. data/test/data/users_guide/layout8_html.rbhtml +5 -0
  149. data/test/data/users_guide/layout8_xhtml.rbhtml +6 -0
  150. data/test/data/users_guide/layout9.rbhtml +25 -0
  151. data/test/data/users_guide/sidemenu.rbhtml +5 -0
  152. data/test/data/users_guide/user_app.cgi +39 -0
  153. data/test/data/users_guide/user_app.result +30 -0
  154. data/test/data/users_guide/user_create.rbhtml +6 -0
  155. data/test/data/users_guide/user_edit.rbhtml +7 -0
  156. data/test/data/users_guide/user_form.rbhtml +10 -0
  157. data/test/data/users_guide/user_layout.rbhtml +16 -0
  158. data/test/test_all.rb +23 -0
  159. data/test/test_engine.rb +526 -0
  160. data/test/test_engine.yaml +2039 -0
  161. data/test/test_examples.rb +81 -0
  162. data/test/test_faq.rb +60 -0
  163. data/test/test_htmlhelper.rb +78 -0
  164. data/test/test_main.rb +564 -0
  165. data/test/test_main.yaml +174 -0
  166. data/test/test_template.rb +113 -0
  167. data/test/test_template.yaml +1244 -0
  168. data/test/test_users_guide.rb +75 -0
  169. data/test/testcase-helper.rb +166 -0
  170. metadata +226 -0
data/doc/faq.html ADDED
@@ -0,0 +1,909 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html">
5
+ <title>rbTenjin FAQ</title>
6
+ <meta name="generator" content="kwaser">
7
+ <meta http-equiv="Content-Style-Type" content="text/css">
8
+ <link rel="stylesheet" href="docstyle.css" type="text/css">
9
+ </head>
10
+ <body>
11
+
12
+ <blockquote>
13
+ <div class="mainbody">
14
+
15
+ <div align="left"><h1>rbTenjin FAQ</h1></div>
16
+ <div align="left">
17
+ last update: $Date: 2007-08-04 13:23:33 +0900 (Sat, 04 Aug 2007) $<br>
18
+ </div>
19
+
20
+ <p>Release: 0.6.0
21
+ </p>
22
+ <p>Table of contents:
23
+ <ul>
24
+ <li><a href="#faq-basic">Basic</a>
25
+ <ul>
26
+ <li><a href="#faq-syntax-error">I got an SyntaxError exception.</a>
27
+ </li>
28
+ <li><a href="#faq-delete-newline">'#{@_content}' includes extra newline at end. Can I delete it?</a>
29
+ </li>
30
+ <li><a href="#faq-change-funcname">Can I change 'escape()' function name?</a>
31
+ </li>
32
+ <li><a href="#faq-change-bufname">Can I change '_buf' variable name?</a>
33
+ </li>
34
+ </ul>
35
+ </li>
36
+ <li><a href="#faq-template">Template</a>
37
+ <ul>
38
+ <li><a href="#faq-template-args">Is it possible to specify variables passed to template?</a>
39
+ </li>
40
+ <li><a href="#faq-eruby-template">Is there any way to use eRuby template?</a>
41
+ </li>
42
+ <li><a href="#faq-exprpat">Is it able to change embedded expression pattern?</a>
43
+ </li>
44
+ <li><a href="#faq-m17n">Does rbTenjin support M17N?</a>
45
+ </li>
46
+ </ul>
47
+ </li>
48
+ <li><a href="#faq-layout">Layout Template</a>
49
+ <ul>
50
+ <li><a href="#faq-change-layout-template">Can I change layout template name in a template file?</a>
51
+ </li>
52
+ <li><a href="#faq-nested-layout-template">Can I nest layout templates for any depth?</a>
53
+ </li>
54
+ <li><a href="#faq-diable-layout">Can I disable default layout template for a certain template?</a>
55
+ </li>
56
+ <li><a href="#faq-template-inheritance">Is Django-like "Template Inheritance" supported?</a>
57
+ </li>
58
+ </ul>
59
+ </li>
60
+ <li><a href="#faq-performance">Performance</a>
61
+ <ul>
62
+ <li><a href="#How fast is rbTenjin compared with other solutions?">How fast is rbTenjin compared with other solutions?</a>
63
+ </li>
64
+ <li><a href="#faq-why-so-fast">Why rbTenjin is so fast?</a>
65
+ </li>
66
+ <li><a href="#faq-performance-tuning">Is there any way to get more speed?</a>
67
+ </li>
68
+ </ul>
69
+ </li>
70
+ </ul>
71
+ </p>
72
+ <a name="faq-basic"></a>
73
+ <h2 class="section1">Basic</h2>
74
+ <a name="faq-syntax-error"></a>
75
+ <h3 class="section2">I got an SyntaxError exception.</h3>
76
+ <p>Command-line option '-z' checks syntax of template file.
77
+ You should check template by it.
78
+ </p>
79
+ <a name="ex1.rbhtml"></a>
80
+ <div class="program_caption">
81
+ File 'ex1.rbhtml':</div>
82
+ <pre class="program">&lt;ul&gt;
83
+ &lt;?rb (0..10).each { |i| ?&gt;
84
+ &lt;li&gt;#{i}&lt;/li&gt;
85
+ &lt;?rb end ?&gt;
86
+ &lt;/ul&gt;
87
+ </pre>
88
+ <a name="ex1_chksyntax.result"></a>
89
+ <div class="terminal_caption">
90
+ Result:</div>
91
+ <pre class="terminal">$ rbtenjin <strong>-wz</strong> ex1.rbhtml
92
+ ex1.rbhtml:4: syntax error, unexpected kEND, expecting '}'
93
+ ex1.rbhtml:5: syntax error, unexpected $end, expecting '}'
94
+ </pre>
95
+ <br>
96
+
97
+
98
+ <a name="faq-delete-newline"></a>
99
+ <h3 class="section2">'#{@_content}' includes extra newline at end. Can I delete it?</h3>
100
+ <p>Yes. You can use '<code>&lt;?rb echo(@_content) ?&gt;</code>' or '<code>&lt;?rb _buf &lt;&lt; @_content ?&gt;</code>' instead of '<code>#{@_conent}</code>'.
101
+ </p>
102
+ <a name="ex2-layout.rbhtml"></a>
103
+ <div class="program_caption">
104
+ File 'ex2-layout.rbhtml':</div>
105
+ <pre class="program">&lt;!-- --&gt;
106
+ <strong>#{@_content}</strong>
107
+ &lt;!-- --&gt;
108
+
109
+ &lt;!-- --&gt;
110
+ <strong>&lt;?rb echo(@_content) ?&gt;</strong>
111
+ &lt;!-- --&gt;
112
+
113
+ &lt;!-- --&gt;
114
+ <strong>&lt;?rb _buf &lt;&lt; @_content ?&gt;</strong>
115
+ &lt;!-- --&gt;
116
+ </pre>
117
+ <a name="ex2-content.rbhtml"></a>
118
+ <div class="program_caption">
119
+ File 'ex2-content.rbhtml':</div>
120
+ <pre class="program">foo
121
+ bar
122
+ baz
123
+ </pre>
124
+ <a name="ex2_removenl.result"></a>
125
+ <div class="terminal_caption">
126
+ Result:</div>
127
+ <pre class="terminal">$ rbtenjin --layout=ex2-layout.rbhtml ex2-content.rbhtml
128
+ &lt;!-- --&gt;
129
+ foo
130
+ bar
131
+ baz
132
+
133
+ &lt;!-- --&gt;
134
+
135
+ &lt;!-- --&gt;
136
+ foo
137
+ bar
138
+ baz
139
+ &lt;!-- --&gt;
140
+
141
+ &lt;!-- --&gt;
142
+ foo
143
+ bar
144
+ baz
145
+ &lt;!-- --&gt;
146
+ </pre>
147
+ <br>
148
+
149
+
150
+ <a name="faq-change-funcname"></a>
151
+ <h3 class="section2">Can I change 'escape()' function name?</h3>
152
+ <p>Yes. You can change them by setting <code>:escapefunc</code> option for Tenjin::Template.new() or Tenjin::Engine.new().
153
+ </p>
154
+ <a name="ex3.rb"></a>
155
+ <div class="program_caption">
156
+ File 'ex3.rb':</div>
157
+ <pre class="program">require 'tenjin'
158
+ engine = Tenjin::Engine.new(<strong>:escapefunc=&gt;'CGI.escapeHTML'</strong>)
159
+ template = engine.get_template('ex3.rbhtml')
160
+ print template.script
161
+ </pre>
162
+ <a name="ex3.rbhtml"></a>
163
+ <div class="program_caption">
164
+ File 'ex3.rbhtml':</div>
165
+ <pre class="program">Hello ${@name}!
166
+ </pre>
167
+ <a name="ex3_escapefunc1.result"></a>
168
+ <div class="program_caption">
169
+ Result:</div>
170
+ <pre class="program">$ ruby ex3.rb
171
+ _buf &lt;&lt; %Q`Hello #{<strong>CGI.escapeHTML</strong>((@name).to_s)}!\n`
172
+ </pre>
173
+ <p>Command-line option '--escapefunc=<em>name</em>' is equivarent to the above.
174
+ </p>
175
+ <a name="ex3_escapefunc2.result"></a>
176
+ <div class="program_caption">
177
+ Result:</div>
178
+ <pre class="program">$ rbtenjin -sb <strong>--escapefunc=CGI.escapeHTML</strong> ex3.rbhtml
179
+ _buf &lt;&lt; %Q`Hello #{<strong>CGI.escapeHTML</strong>((@name).to_s)}!\n`
180
+ </pre>
181
+ <br>
182
+
183
+
184
+ <a name="faq-change-bufname"></a>
185
+ <h3 class="section2">Can I change '_buf' variable name?</h3>
186
+ <p>No. Variable name '_buf' should not and will never be changed.
187
+ </p>
188
+ <br>
189
+
190
+
191
+ <br>
192
+
193
+
194
+ <a name="faq-template"></a>
195
+ <h2 class="section1">Template</h2>
196
+ <a name="faq-template-args"></a>
197
+ <h3 class="section2">Is it possible to specify variables passed to template?</h3>
198
+ <p>Yes. You can specify template arguments by '<code>&lt;?rb #@ARGS arg1, arg2, arg3 ?&gt;</code>'.
199
+ </p>
200
+ <a name="ex5.rbhtml"></a>
201
+ <div class="program_caption">
202
+ File 'ex5-layout.rbhtml'</div>
203
+ <pre class="program">&lt;?xml version="1.0 ?&gt;
204
+ <strong>&lt;?rb #@ARGS x, y ?&gt;</strong>
205
+ &lt;p&gt;
206
+ x = #{x}
207
+ y = #{y}
208
+ z = #{z}
209
+ &lt;/p&gt;
210
+ </pre>
211
+ <p>Template arguments line is converted into local variable assignment statements.
212
+ </p>
213
+ <a name="ex5_template_args.source"></a>
214
+ <div class="terminal_caption">
215
+ Source code</div>
216
+ <pre class="terminal">$ rbtenjin -s ex5.rbhtml
217
+ _buf = ''; _buf &lt;&lt; %Q`&lt;?xml version="1.0 ?&gt;\n`
218
+ <strong> x = @x; y = @y;</strong>
219
+ _buf &lt;&lt; %Q`&lt;p&gt;
220
+ x = #{x}
221
+ y = #{y}
222
+ z = #{z}
223
+ &lt;/p&gt;\n`
224
+ _buf.to_s
225
+ </pre>
226
+ <p>Undeclared arguments are not available even when they are passed via context object.
227
+ </p>
228
+ <div class="terminal_caption">
229
+ Result:</div>
230
+ <pre class="terminal">$ rbtenjin -c 'x=10; y=20; z=30' ex5.rbhtml
231
+ ex5.rbhtml:6:in `_render': undefined local variable or method `z' for #&lt;Tenjin::Context:0x35a9e4&gt; (NameError)
232
+ </pre>
233
+ <br>
234
+
235
+
236
+ <a name="faq-eruby-template"></a>
237
+ <h3 class="section2">Is there any way to use eRuby template?</h3>
238
+ <p>Yes. It is able to use eRuby template files by Tenjin::ErubisTemplate class.
239
+ </p>
240
+ <p>It is required to install <a href="http://www.kuwata-lab.com/erubis">Erubis</a> to use Tenjin::ErubisTemplate class.
241
+ </p>
242
+ <a name="ex6-layout.rhtml"></a>
243
+ <div class="program_caption">
244
+ File 'ex6-layout.rhtml'</div>
245
+ <pre class="program">&lt;html&gt;
246
+ &lt;body&gt;
247
+ &lt;h1&gt;<strong>&lt;%=h @title %&gt;</strong>&lt;/h1&gt;
248
+ <strong>&lt;%= @_content %&gt;</strong>
249
+ &lt;/body&gt;
250
+ &lt;/html&gt;
251
+ </pre>
252
+ <a name="ex6-content.rhtml"></a>
253
+ <div class="program_caption">
254
+ File 'ex6-content.rhtml'</div>
255
+ <pre class="program"> <strong>&lt;% @title = 'eRuby template example' %&gt;</strong>
256
+ &lt;ul&gt;
257
+ <strong>&lt;% for item in @items %&gt;</strong>
258
+ &lt;li&gt;<strong>&lt;%=h item %&gt;</strong>&lt;/li&gt;
259
+ <strong>&lt;% end %&gt;</strong>
260
+ &lt;/ul&gt;
261
+ </pre>
262
+ <a name="ex6.rb"></a>
263
+ <div class="program_caption">
264
+ File 'ex6-main.rb':</div>
265
+ <pre class="program"><strong>require 'erubis'</strong>
266
+ require 'tenjin'
267
+
268
+ include Erubis::XmlHelper
269
+
270
+ context = { :items =&gt; ['&lt;AAA&gt;', 'B&amp;B', '"CCC"'] }
271
+ engine = Tenjin::Engine.new(:layout=&gt;'ex6-layout.rhtml',
272
+ <strong>:templateclass=&gt;Tenjin::ErubisTemplate</strong>)
273
+ output = engine.render('ex6-content.rhtml', context)
274
+ print output
275
+ </pre>
276
+ <a name="ex6_eruby.result"></a>
277
+ <div class="terminal_caption">
278
+ Result:</div>
279
+ <pre class="terminal">$ ruby ex6.rb
280
+ &lt;html&gt;
281
+ &lt;body&gt;
282
+ &lt;h1&gt;eRuby template example&lt;/h1&gt;
283
+ &lt;ul&gt;
284
+ &lt;li&gt;&amp;lt;AAA&amp;gt;&lt;/li&gt;
285
+ &lt;li&gt;B&amp;amp;B&lt;/li&gt;
286
+ &lt;li&gt;&amp;quot;CCC&amp;quot;&lt;/li&gt;
287
+ &lt;/ul&gt;
288
+
289
+ &lt;/body&gt;
290
+ &lt;/html&gt;
291
+ </pre>
292
+ <br>
293
+
294
+
295
+ <a name="faq-exprpat"></a>
296
+ <h3 class="section2">Is it able to change embedded expression pattern?</h3>
297
+ <p>Yes, you can create subclass of Template class and override embedded expression pattern.
298
+ </p>
299
+ <a name="ex7-expr-pattern.rbhtml"></a>
300
+ <div class="program_caption">
301
+ ex7-expr-pattern.rbhtml:</div>
302
+ <pre class="program">&lt;p&gt;HTML escaped: ${@value}&lt;/p&gt;
303
+ &lt;p&gt;not escaped: #{@value}&lt;/p&gt;
304
+ &lt;p&gt;not escaped: <strong>&lt;%= @value %&gt;</strong>&lt;/p&gt;
305
+ </pre>
306
+ <a name="ex7-expr-pattern.rb"></a>
307
+ <div class="program_caption">
308
+ ex7-expr-pattern.rb:</div>
309
+ <pre class="program">require 'tenjin'
310
+
311
+ class MyTemplate &lt; Tenjin::Template
312
+
313
+ ## return pattern object for embedded expressions
314
+ def <strong>expr_pattern()</strong>
315
+ return /([$#])\{(.*?)\}|&lt;%=(.*?)%&gt;/m
316
+ end
317
+
318
+ ## if you don't use '#{...}', you must escape '#' in addition to '\\' and '`'
319
+ #def escape_str(str)
320
+ # return str.gsub(/[\\`\#]/, '\\\\\&amp;')
321
+ #end
322
+
323
+ ## return expression string and flag whether escape or not from matched object
324
+ def <strong>get_expr_and_escapeflag(match)</strong>
325
+ if match[1]
326
+ expr = match[2]
327
+ escapeflag = match[1] == '$'
328
+ else
329
+ expr = match[3].strip()
330
+ escapeflag = false
331
+ end
332
+ return expr, escapeflag
333
+ end
334
+
335
+ end
336
+
337
+ if __FILE__ == $0
338
+ context = { :value =&gt; 'AAA&amp;BBB' }
339
+ engine = Tenjin::Engine.new(<strong>:templateclass=&gt;MyTemplate</strong>)
340
+ output = engine.render('ex7-expr-pattern.rbhtml', context)
341
+ puts output
342
+ end
343
+ </pre>
344
+ <a name="ex7_expr_pattern.result"></a>
345
+ <div class="terminal_caption">
346
+ Result:</div>
347
+ <pre class="terminal">$ ruby ex7-expr-pattern.rb
348
+ &lt;p&gt;HTML escaped: AAA&amp;amp;BBB&lt;/p&gt;
349
+ &lt;p&gt;not escaped: AAA&amp;BBB&lt;/p&gt;
350
+ &lt;p&gt;not escaped: AAA&amp;BBB&lt;/p&gt;
351
+ </pre>
352
+ <br>
353
+
354
+
355
+ <a name="faq-m17n"></a>
356
+ <h3 class="section2">Does rbTenjin support M17N?</h3>
357
+ <p>No, but it is easy to support M17N.
358
+ The point is:
359
+ </p>
360
+ <ul type="disc">
361
+ <li>Change cache filename according to language.
362
+ For example, create cache file 'file.rbhtml.en.cache', 'file.rbhtml.fr.cache', 'file.rbhtml.it.cache', and so on from template file 'file.rbhtml'.
363
+ </li>
364
+ <li>Create Engine object for each language.
365
+ </li>
366
+ <li>(optinal) Use preprocessing for performance reason.
367
+ </li>
368
+ </ul>
369
+ <p>The following is an example to generate M17N pages from a template file.
370
+ </p>
371
+ <a name="ex8-m18n.rbhtml"></a>
372
+ <div class="program_caption">
373
+ ex8-m18n.rbhtml:</div>
374
+ <pre class="program">&lt;div&gt;
375
+ &lt;?RB ## '_()' represents translator method ?&gt;
376
+ &lt;p&gt;<strong>${{_('Hello')}}</strong> ${@username}!&lt;/p&gt;
377
+ &lt;/div&gt;
378
+ </pre>
379
+ <a name="ex8-m18n.rb"></a>
380
+ <div class="program_caption">
381
+ ex8-m18n.rb:</div>
382
+ <pre class="program">require 'tenjin'
383
+
384
+ ##
385
+ ## message catalog to translate message
386
+ ##
387
+ MESSAGE_CATALOG = {
388
+ 'en' =&gt; { 'Hello' =&gt; 'Hello',
389
+ 'Good bye'=&gt; 'Good bye', },
390
+ 'fr' =&gt; { 'Hello' =&gt; 'Bonjour',
391
+ 'Good bye'=&gt; 'Au revoir', },
392
+ }
393
+
394
+
395
+ ##
396
+ ## add translation method to Context class
397
+ ##
398
+ class Tenjin::Context
399
+
400
+ def _(message_key)
401
+ message_dict = MESSAGE_CATALOG[@_lang]
402
+ return message_key unless message_dict
403
+ return message_dict[message_key] || message_key
404
+ end
405
+
406
+ end
407
+
408
+
409
+ ##
410
+ ## engine class which supports M17N
411
+ ##
412
+ class M17NEngine &lt; Tenjin::Engine
413
+
414
+ <strong>attr_accessor :lang</strong>
415
+
416
+ ## constructor takes ':lang' options
417
+ def initialize(properties={})
418
+ super(properties)
419
+ @lang = properties[:lang] || 'en' # set language
420
+ end
421
+
422
+ ## change cache filename to 'file.html.lang.cache'
423
+ <strong>def cachename(filename)</strong>
424
+ <strong>return "#{filename}.#{@lang}.cache"</strong>
425
+ <strong>end</strong>
426
+
427
+ ## set language to context object
428
+ def hook_context(context)
429
+ context = super(context)
430
+ context['_lang'] = @lang
431
+ return context
432
+ end
433
+
434
+ end
435
+
436
+
437
+ ##
438
+ ## test program
439
+ ##
440
+ if $0 == __FILE__
441
+
442
+ template_name = 'ex8-m18n.rbhtml'
443
+ context = { :username =&gt; 'World' }
444
+
445
+ ## engine for english
446
+ engine = <strong>M17NEngine</strong>.new(:preprocess=&gt;true)
447
+ output = engine.render(template_name, context) # same template
448
+ puts "--- lang: %s ---" % engine.lang
449
+ puts output
450
+ puts
451
+
452
+ ## engine for French
453
+ engine = <strong>M17NEngine</strong>.new(:preprocess=&gt;true, <strong>:lang=&gt;'fr'</strong>)
454
+ output = engine.render(template_name, context) # same template
455
+ puts "--- lang: %s ---" % engine.lang
456
+ puts output
457
+
458
+ end
459
+ </pre>
460
+ <a name="ex8_m18n.result"></a>
461
+ <div class="terminal_caption">
462
+ Result:</div>
463
+ <pre class="terminal">$ ruby ex8-m18n.rb
464
+ --- lang: en ---
465
+ &lt;div&gt;
466
+ &lt;p&gt;<strong>Hello</strong> World!&lt;/p&gt;
467
+ &lt;/div&gt;
468
+
469
+ --- lang: fr ---
470
+ &lt;div&gt;
471
+ &lt;p&gt;<strong>Bonjour</strong> World!&lt;/p&gt;
472
+ &lt;/div&gt;
473
+ </pre>
474
+ <p>rbTenjin doesn't provide M17N feature directly because requirements for M17N are
475
+ different for each applications or frameworks.
476
+ Some applications or frameworks adapt GetText library and others use its original M17N library.
477
+ What rbTenjin should do is not to provide M17N feature but to show an example to support M17N.
478
+ </p>
479
+ <br>
480
+
481
+
482
+ <br>
483
+
484
+
485
+ <a name="faq-layout"></a>
486
+ <h2 class="section1">Layout Template</h2>
487
+ <a name="faq-change-layout-template"></a>
488
+ <h3 class="section2">Can I change layout template name in a template file?</h3>
489
+ <p>Yes. If you set <code>@_layout</code>,
490
+ its value is regarded as layout template name.
491
+ </p>
492
+ <ul type="disc">
493
+ <li>You can specify template file name (ex. 'user_list.rbhtml') or template short name (ex. :list).
494
+ </li>
495
+ <li>If you set true to '@_layout', default layout template name is used instead.
496
+ </li>
497
+ <li>It is able to N-th level nested template.
498
+ </li>
499
+ </ul>
500
+ <p>See the next section for details.
501
+ </p>
502
+ <br>
503
+
504
+
505
+ <a name="faq-nested-layout-template"></a>
506
+ <h3 class="section2">Can I nest layout templates for any depth?</h3>
507
+ <p>Yes. If you set <code>@_layout</code>,
508
+ you can nest layout templates in any depth.
509
+ </p>
510
+ <p>The following example shows that:
511
+ </p>
512
+ <ul type="disc">
513
+ <li>'ex8-content.rbhtml' uses 'ex8-mylayout.rbhtml' as layout template.
514
+ </li>
515
+ <li>'ex8-mylayout.rbhtml' uses 'ex8-baselayout.rbhtml' as layout template.
516
+ </li>
517
+ </ul>
518
+ <a name="ex9-content.rbhtml"></a>
519
+ <div class="program_caption">
520
+ File 'ex9-content.rbhtml':</div>
521
+ <pre class="program">&lt;?rb @title = 'Changing Layout Template Test' ?&gt;
522
+ &lt;?rb ## specify layout template name ?&gt;
523
+ <strong>&lt;?rb @_layout = 'ex9-mylayout.rbhtml' ?&gt;</strong>
524
+ foo
525
+ bar
526
+ baz
527
+ </pre>
528
+ <a name="ex9-mylayout.rbhtml"></a>
529
+ <div class="program_caption">
530
+ File 'ex9-mylayout.rbhtml':</div>
531
+ <pre class="program">&lt;?rb ## use default layout template name ?&gt;
532
+ <strong>&lt;?rb @_layout = true ?&gt;</strong>
533
+ &lt;div id="content"&gt;
534
+ <strong>&lt;?rb _buf &lt;&lt; @_content ?&gt;</strong>
535
+ &lt;/div&gt;
536
+ </pre>
537
+ <a name="ex9-baselayout.rbhtml"></a>
538
+ <div class="program_caption">
539
+ File 'ex9-baselayout.rbhtml':</div>
540
+ <pre class="program">&lt;html&gt;
541
+ &lt;body&gt;
542
+ &lt;?rb if @title ?&gt;
543
+ &lt;h1&gt;${@title}&lt;/h1&gt;
544
+ &lt;?rb end ?&gt;
545
+ <strong>&lt;?rb _buf &lt;&lt; @_content ?&gt;</strong>
546
+ &lt;/body&gt;
547
+ &lt;/html&gt;
548
+ </pre>
549
+ <a name="ex9_changelayout.result"></a>
550
+ <div class="terminal_caption">
551
+ Result:</div>
552
+ <pre class="terminal">$ rbtenjin --layout=ex9-baselayout.rbhtml ex9-content.rbhtml
553
+ &lt;html&gt;
554
+ &lt;body&gt;
555
+ &lt;h1&gt;Changing Layout Template Test&lt;/h1&gt;
556
+ &lt;div id="content"&gt;
557
+ foo
558
+ bar
559
+ baz
560
+ &lt;/div&gt;
561
+ &lt;/body&gt;
562
+ &lt;/html&gt;
563
+ </pre>
564
+ <br>
565
+
566
+
567
+ <a name="faq-diable-layout"></a>
568
+ <h3 class="section2">Can I disable default layout template for a certain template?</h3>
569
+ <p>Yes. If you set false to @_layout, default layout template will not be applied.
570
+ </p>
571
+ <br>
572
+
573
+
574
+ <a name="faq-template-inheritance"></a>
575
+ <h3 class="section2">Is Django-like "Template Inheritance" supported?</h3>
576
+ <p>No, but you can emulate it partially by combination of template capturing and '@_layout'.
577
+ </p>
578
+ <a name="ex10-baselayout.rbhtml"></a>
579
+ <div class="program_caption">
580
+ File 'ex10-baselayout.rbhtml':</div>
581
+ <pre class="program">&lt;html&gt;
582
+ &lt;body&gt;
583
+
584
+ &lt;?rb ## if variable '@header_part' is defined then print it, ?&gt;
585
+ &lt;?rb ## else print default header part. ?&gt;
586
+ &lt;div id="header"&gt;
587
+ <strong>&lt;?rb unless captured_as(:header_part) ?&gt;</strong>
588
+ &lt;img src="img/logo.png" alt="logo" ?&gt;
589
+ <strong>&lt;?rb end ?&gt;</strong>
590
+ &lt;/div&gt;
591
+
592
+ &lt;?rb ## main content part ?&gt;
593
+ &lt;div id="content"&gt;
594
+ &lt;?rb _buf &lt;&lt; @content_part ?&gt;
595
+ &lt;/div&gt;
596
+
597
+ &lt;?rb ## if variable '@footer_part' is defined then print it, ?&gt;
598
+ &lt;?rb ## else print default footer part. ?&gt;
599
+ &lt;div id="footer"&gt;
600
+ <strong>&lt;?rb unless captured_as(:footer_part) ?&gt;</strong>
601
+ &lt;hr /&gt;
602
+ &lt;em&gt;webmaster@example.com&lt;/em&gt;
603
+ <strong>&lt;?rb end ?&gt;</strong>
604
+ &lt;/div&gt;
605
+
606
+ &lt;/body&gt;
607
+ &lt;/html&gt;
608
+ </pre>
609
+ <a name="ex10-customlayout.rbhtml"></a>
610
+ <div class="program_caption">
611
+ File 'ex10-customlayout.rbhtml':</div>
612
+ <pre class="program">&lt;?rb ## '@_layout' variable is equivarent to '{% extends "foobar.html" %}' ?&gt;
613
+ &lt;?rb ## in Django template engine. ?&gt;
614
+ <strong>&lt;?rb @_layout = 'ex10-baselayout.rbhtml' ?&gt;</strong>
615
+
616
+ &lt;?rb ## you can override header or footer by capturing. ?&gt;
617
+ <strong>&lt;?rb start_capture(:footer_part) ?&gt;</strong>
618
+ &lt;address style="text-align:right"&gt;
619
+ copyright&amp;copy; 2007 kuwata-lab all rights reserved&lt;br /&gt;
620
+ &lt;a href="webmaster&amp;#64;kuwata-lab.com"&gt;webmaster&amp;#64;kuwata-lab.com&lt;/a&gt;
621
+ &lt;/address&gt;
622
+ <strong>&lt;?rb stop_capture() ?&gt;</strong>
623
+ </pre>
624
+ <a name="ex10-content.rbhtml"></a>
625
+ <div class="program_caption">
626
+ File 'ex10-content.rbhtml':</div>
627
+ <pre class="program">&lt;?rb ## '@_layout' variable is equivarent to '{% extends "foobar.html" %}' ?&gt;
628
+ &lt;?rb ## in Django template engine. ?&gt;
629
+ <strong>&lt;?rb @_layout = 'ex10-customlayout.rbhtml' ?&gt;</strong>
630
+
631
+ &lt;?rb ## main content part ?&gt;
632
+ <strong>&lt;?rb start_capture(:content_part) ?&gt;</strong>
633
+ &lt;ul&gt;
634
+ &lt;?rb for item in @items ?&gt;
635
+ &lt;li&gt;${item}&lt;/li&gt;
636
+ &lt;?rb end ?&gt;
637
+ &lt;/ul&gt;
638
+ <strong>&lt;?rb stop_capture() ?&gt;</strong>
639
+ </pre>
640
+ <p>'<code>captured_as()</code>' is a pre-defined helper function.
641
+ For example,
642
+ </p>
643
+ <pre class="program">&lt;?rb <strong>unless captured_as(:header_part):</strong> ?&gt;
644
+ &lt;img src="img/logo.png" alt="logo" ?&gt;
645
+ &lt;?rb <strong>end</strong> ?&gt;
646
+ </pre>
647
+ <p>is equivarent to the following.
648
+ </p>
649
+ <pre class="program">&lt;?rb <strong>if @header_part:</strong> ?&gt;
650
+ &lt;?rb <strong>_buf &lt;&lt; @header_part</strong> ?&gt;
651
+ &lt;?rb <strong>else</strong> ?&gt;
652
+ &lt;img src="img/logo.png" alt="logo" ?&gt;
653
+ &lt;?rb <strong>end</strong> ?&gt;
654
+ </pre>
655
+ <p>The following is the result. It shows that footer part in baselayout is overrided by other templates.
656
+ </p>
657
+ <a name="ex10_inherit.result"></a>
658
+ <div class="terminal_caption">
659
+ Result:</div>
660
+ <pre class="terminal">$ rbtenjin -c "@items=['AAA', 'BBB', 'CCC']" ex10-content.rbhtml
661
+ &lt;html&gt;
662
+ &lt;body&gt;
663
+
664
+ &lt;div id="header"&gt;
665
+ &lt;img src="img/logo.png" alt="logo" ?&gt;
666
+ &lt;/div&gt;
667
+
668
+ &lt;div id="content"&gt;
669
+ &lt;ul&gt;
670
+ &lt;li&gt;AAA&lt;/li&gt;
671
+ &lt;li&gt;BBB&lt;/li&gt;
672
+ &lt;li&gt;CCC&lt;/li&gt;
673
+ &lt;/ul&gt;
674
+ &lt;/div&gt;
675
+
676
+ &lt;div id="footer"&gt;
677
+ &lt;address style="text-align:right"&gt;
678
+ copyright&amp;copy; 2007 kuwata-lab all rights reserved&lt;br /&gt;
679
+ &lt;a href="webmaster&amp;#64;kuwata-lab.com"&gt;webmaster&amp;#64;kuwata-lab.com&lt;/a&gt;
680
+ &lt;/address&gt;
681
+ &lt;/div&gt;
682
+
683
+ &lt;/body&gt;
684
+ &lt;/html&gt;
685
+ </pre>
686
+ <br>
687
+
688
+
689
+ <br>
690
+
691
+
692
+ <a name="faq-performance"></a>
693
+ <h2 class="section1">Performance</h2>
694
+ <a name="How fast is rbTenjin compared with other solutions?"></a>
695
+ <h3 class="section2">How fast is rbTenjin compared with other solutions?</h3>
696
+ <p>rbTenjin contains benchmark script.
697
+ This shows that rbTenjin works much faster than other solutions.
698
+ </p>
699
+ <div class="terminal_caption">
700
+ MacOS X 10.4 Tiger, Intel CoreDuo 1.83GHz, Memory 2GB</div>
701
+ <pre class="terminal">$ cd rbtenjin-X.X.X/benchmark
702
+ $ ruby -v
703
+ ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.9.1]
704
+ $ ruby bench.rb -n 10000
705
+ user system total real
706
+ eruby 12.190000 0.260000 12.450000 ( 12.464225)
707
+ eruby-cache 11.320000 0.410000 11.730000 ( 11.756440)
708
+ erb 36.190000 0.370000 36.560000 ( 36.694964)
709
+ erb-reuse 10.720000 0.020000 10.740000 ( 10.770338)
710
+ erubis 10.130000 0.310000 10.440000 ( 10.476733)
711
+ erubis-reuse 6.380000 0.010000 6.390000 ( 6.405158)
712
+ tenjin 6.600000 0.410000 7.010000 ( 7.021953)
713
+ tenjin-nocache 8.180000 0.360000 8.540000 ( 8.562649)
714
+ tenjin-reuse 4.370000 0.180000 4.550000 ( 4.549724)
715
+ </pre>
716
+ <p>In addition, module size of rbTenjin is small, and it is very light-weight to import it.
717
+ This is important for CGI program.
718
+ Other solutions may be very heavy to import the module and suitable only for apache module or FastCGI.
719
+ </p>
720
+ <br>
721
+
722
+
723
+ <a name="faq-why-so-fast"></a>
724
+ <h3 class="section2">Why rbTenjin is so fast?</h3>
725
+ <p>Because it doesn't use template engine original language.
726
+ </p>
727
+ <p>Other template engines, such as Template-Toolkit(perl), Django(python), or Smarty(php),
728
+ has their original languages.
729
+ This is not good idea for script language because:
730
+ </p>
731
+ <ul type="disc">
732
+ <li>They are slow.
733
+ </li>
734
+ <li>Implementation will be complex.
735
+ </li>
736
+ <li>Learning cost is high.
737
+ </li>
738
+ </ul>
739
+ <p>In addition, rbTenjin is faster than Jakarta Velocity which is a very popular template engine in Java.
740
+ (It means that dynamic Java is slower than script languages.)
741
+ </p>
742
+ <p>Template engine should use their host language directly unless there are some kind of reasons.
743
+ </p>
744
+ <br>
745
+
746
+
747
+ <a name="faq-performance-tuning"></a>
748
+ <h3 class="section2">Is there any way to get more speed?</h3>
749
+ <ul type="disc">
750
+ <li>Tenjin::ArrayBufferTemplate may be a litte faster than Tenjin::Template.
751
+ Tenjin::ArrayBufferTemplate generates Ruby code which use Array buffer and Array#push() method.
752
+ <a name="ex11.rbhtml"></a>
753
+ <div class="program_caption">
754
+ File 'ex11.rbhtml':</div>
755
+ <pre class="program">&lt;table&gt;
756
+ &lt;?rb @items.each_with_index do |item, i| ?&gt;
757
+ &lt;tr&gt;
758
+ &lt;td&gt;#{i}&lt;/td&gt;
759
+ &lt;td&gt;${item}&lt;/td&gt;
760
+ &lt;/tr&gt;
761
+ &lt;?rb end ?&gt;
762
+ &lt;/table&gt;
763
+ </pre>
764
+ <a name="ex11.source"></a>
765
+ <div class="terminal_caption">
766
+ Ruby code:</div>
767
+ <pre class="terminal">$ rbtenjin -s <strong>--templateclass=Tenjin::ArrayBufferTemplate</strong> ex11.rbhtml
768
+ <strong>_buf = []</strong>; <strong>_buf.push</strong>('&lt;table&gt;
769
+ '); @items.each_with_index do |item, i|
770
+ <strong>_buf.push</strong>(' &lt;tr&gt;
771
+ &lt;td&gt;', (i).to_s, '&lt;/td&gt;
772
+ &lt;td&gt;', escape((item).to_s), '&lt;/td&gt;
773
+ &lt;/tr&gt;
774
+ '); end
775
+ <strong>_buf.push</strong>('&lt;/table&gt;
776
+ ');
777
+ _buf.to_s
778
+ </pre>
779
+ <a name="ex11.rb"></a>
780
+ <div class="program_caption">
781
+ File 'ex11.rb':</div>
782
+ <pre class="program">require 'tenjin'
783
+ engine = Tenjin::Engine.new(<strong>:templateclass=&gt;Tenjin::ArrayBufferTemplate</strong>)
784
+ context = { :items=&gt;['AAA', 'BBB', 'CCC'] }
785
+ output = engine.render('ex11.rbhtml', context)
786
+ puts output
787
+ </pre>
788
+ <a name="ex11_arraybuffer.result"></a>
789
+ <div class="terminal_caption">
790
+ Result:</div>
791
+ <pre class="terminal">$ ruby ex11.rb
792
+ &lt;table&gt;
793
+ &lt;tr&gt;
794
+ &lt;td&gt;0&lt;/td&gt;
795
+ &lt;td&gt;AAA&lt;/td&gt;
796
+ &lt;/tr&gt;
797
+ &lt;tr&gt;
798
+ &lt;td&gt;1&lt;/td&gt;
799
+ &lt;td&gt;BBB&lt;/td&gt;
800
+ &lt;/tr&gt;
801
+ &lt;tr&gt;
802
+ &lt;td&gt;2&lt;/td&gt;
803
+ &lt;td&gt;CCC&lt;/td&gt;
804
+ &lt;/tr&gt;
805
+ &lt;/table&gt;
806
+ </pre>
807
+ <p> The following is an example of benchmark of Tenjin::Template and Tenjin::ArrayBufferTemplate.
808
+ This shows that Tenjin::ArrayBufferTemplate is faster than Tenjin::Template when template object (or template engine object) is able to be reused.
809
+ </p>
810
+ <div class="terminal_caption">
811
+ Result:</div>
812
+ <pre class="terminal">$ ruby bench.rb -n 10000 tenjin tenjin-nocache tenjin-reuse \
813
+ tenjin-arrbuf tenjin-arrbuf-nocache tenjin-arrbuf-reuse
814
+ user system total real
815
+ tenjin 6.660000 0.430000 7.090000 ( 7.106619)
816
+ tenjin-nocache 8.260000 0.360000 8.620000 ( 8.655595)
817
+ tenjin-reuse 4.360000 0.060000 <strong>4.420000</strong> ( 4.439242)
818
+ tenjin-arrbuf 6.630000 0.430000 7.060000 ( 7.078775)
819
+ tenjin-arrbuf-nocache 10.150000 0.370000 10.520000 ( 10.574526)
820
+ tenjin-arrbuf-reuse 4.080000 0.070000 <strong>4.150000</strong> ( 4.160438)
821
+ </pre>
822
+ <p> Notice that Tenjin::ArrayBufferTemplate is an experimental.
823
+ </p>
824
+ </li>
825
+ <li>'<code>&lt;?rb _buf &lt;&lt; @_content ?&gt;</code>' may be a litte faster than '<code>#{@_content}</code>' if @_content is large.
826
+ <a name="ex11-layout1.rbhtml"></a>
827
+ <div class="program_caption">
828
+ File 'ex11-layout1.rbhtml':</div>
829
+ <pre class="program">&lt;html&gt;
830
+ &lt;body&gt;
831
+ <strong>#{@_content}</strong>
832
+ &lt;/body&gt;
833
+ &lt;/html&gt;
834
+ </pre>
835
+ <a name="ex11-layout2.rbhtml"></a>
836
+ <div class="program_caption">
837
+ File 'ex11-layout2.rbhtml':</div>
838
+ <pre class="program">&lt;html&gt;
839
+ &lt;body&gt;
840
+ <strong>&lt;?rb _buf &lt;&lt; @_content ?&gt;</strong>
841
+
842
+ &lt;/body&gt;
843
+ &lt;/html&gt;
844
+ </pre>
845
+ <div class="program_caption">
846
+ File 'ex11-content.rbhtml':</div>
847
+ <pre class="program">&lt;table&gt;
848
+ &lt;tbody&gt;
849
+ &lt;?rb for i in (1..100) ?&gt;
850
+ &lt;tr id="row#{i}"&gt;
851
+ &lt;td&gt;#{i}&lt;/td&gt;
852
+ &lt;/tr&gt;
853
+ &lt;?rb end ?&gt;
854
+ &lt;/tbody&gt;
855
+ &lt;/table&gt;
856
+ </pre>
857
+ <a name="ex11-bench.rb"></a>
858
+ <div class="program_caption">
859
+ File 'ex11-bench.rb':</div>
860
+ <pre class="program">## create Engine object for each layout file
861
+ require 'tenjin'
862
+ engine1 = Tenjin::Engine.new(:layout=&gt;'ex11-layout1.rbhtml')
863
+ engine2 = Tenjin::Engine.new(:layout=&gt;'ex11-layout2.rbhtml')
864
+
865
+ ## warm up
866
+ filename = 'ex11-content.rbhtml'
867
+ output1 = engine1.render(filename)
868
+ output2 = engine2.render(filename)
869
+ raise "*** output1 != output2" if output1 != output2
870
+
871
+ ## do benchmark
872
+ require 'benchmark'
873
+ N = 10000
874
+ Benchmark.bm(20) do |job|
875
+ GC.start()
876
+ job.report('layout1') do
877
+ N.times do
878
+ output1 = engine1.render(filename)
879
+ end
880
+ end
881
+ GC.start()
882
+ job.report('layout2') do
883
+ N.times do
884
+ output2 = engine2.render(filename)
885
+ end
886
+ end
887
+ end
888
+ </pre>
889
+ <div class="terminal_caption">
890
+ Result: (MacOS 10.4 Tiger, Intel CoreDuo 1.83GHz, Memory 2GB)</div>
891
+ <pre class="terminal">$ ruby ex11-bench.rb
892
+ user system total real
893
+ layout1 3.920000 0.200000 4.120000 ( 4.201779)
894
+ layout2 3.900000 0.190000 4.090000 ( 4.179283)
895
+ </pre>
896
+ </li>
897
+ </ul>
898
+ <br>
899
+
900
+
901
+ <br>
902
+
903
+
904
+
905
+ </div>
906
+ </blockquote>
907
+
908
+ </body>
909
+ </html>