tenjin 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>