RubyKaigi2009




 All about Erubis
 And the future of template system


makoto kuwata <kwa@kuwata-lab.com>
     http://ww...
I have something to say at first...

  ‣ Thank you for all staff of RubyKaigi!
  ‣ Thank you for all audience who join this...
Agenda

  ‣ Part 1.   Features of Erubis
  ‣ Part 2.Issues about eRuby and solutions
    by Erubis
  ‣ Part 3.   Future of...
Part 1. Features of Erubis



      copyright(c) 2009 kuwata-lab.com all rights reserved.
                                ...
Introduction to Erubis

   ‣ Pure Ruby implementation of eRuby
   ‣ Very fast
     • http://jp.rubyist.net/magazine/?0022-...
Basically Usage
 Ruby program:
  require 'rubygems'        # if need
  require 'erubis'
  str = File.read('template.eruby'...
HTML Escape in Default
  str =<<END           <%= %> ... WITH escaping,
  <%= var %>           <%== %> ... WITHOUT escapin...
Changing Embedded Pattern

   ‣ ex : use '[% %]' instead of '<% %>'
  [% for x in @list %]
   <li>[%= x %]</li>
          ...
Use Hash or Object instead of Binding
example of using Hash                      example of using Object
hash = {         ...
Enhancer
 ‣ Ruby modules which enhances Erubis features
   ## do HTML escape <%= %> in default
   module EscapeEnhancer
  ...
Enhancer (cont')

  ### Enhance which prints into stdout
  ### (you can use print() in statements)
  module StdoutEnhancer...
Usage of Enhancer

                          All you have to do is to include
  ### Ruby                or extend ehnacer ...
Standard Enhancers

 ‣ EscapeEnhancer : escape html in default
 ‣ PercentLineEnhancer : recognize lines starting with '%' ...
Context Data

    ‣ You can specify data to pass into template
      file (context data) in command-line

### command-line
...
Context Data File

    ‣ Load '*.yaml' or '*.rb' as context data file
  $ erubis -f data.yaml template.eruby # YAML
  $ eru...
Debug Print

   ‣ <%=== expr %> represents debug print

  <%=== @var %>                                    No need to writ...
Support Other Programming Langs

 ‣ PHP, Java, JS, C, Perl,Scheme (only for convertion)
  <% for (i=0; i<n; i++) { %>     ...
Conslution

   ‣ Erubis is very functional and extensible
     • HTML escape in default
     • Changing embedded pattern
 ...
Part 2. Issues about eRuby
 and solutions by Erubis


      copyright(c) 2009 kuwata-lab.com all rights reserved.
        ...
Issue : local variables can be changed

   ‣ When using binding(), local variables can be
     non-local
      • Difficult ...
Cause of the issue

   ‣ binding() passes all local variables into
     template file
     • It is impossible to pass only ...
Solution by ERB

   ‣ Nothing, but the author of ERB introduced a
    solution to define custom Struct
     • http://d.hate...
Solution by Erubis

   ‣ Use Hash instead of Binding
                                                            It is ver...
Solution by Erubis (cont')

   ‣ Use Object instead of Binding
    @items = [1, 2, 3];                 <% for x in @items ...
Issue : cost of convertion and parsing
                  ERB
1. 8.6   Erubis::Eruby

                  ERB
1. 8.7   Erubis...
Solution by ERB

   ‣ Convertion cost : nothing
   ‣ Parsing cost : helper to define method
      • Usage is much different...
Solution by Erubis

  ‣ Convertion cost : cache Ruby code into file
    • 1st time : save converted Ruby code into *.cache ...
Solution by Erubis (cont')

   ‣ Parsing cost : keep ruby code as Proc object
      • The same way to use
      • Almost t...
Issue: extra line breaks

    ‣ eRuby outpus extra line breaks
       • Big problem for non-HTML text

               Extr...
Solution by ERB
   ‣ Provides various trim mode
     • ">" : removes LF at the end of line
     • "<>" : removes LF if "<%...
Solution by Erubis

   ‣ Change operation between embedded
     statement and expression
     • <% stmt %> : remove spaces...
Comparison of solutions

                                 ERB                                Erubis

   eRuby spec
   comp...
Hint to think

   ‣ "Extra line breaks" problem has been
     recognized since early times
      • [ruby-list:18894] extra...
Issue : Escape HTML in default

   ‣ <%= expr %> should be HTML escaped in
     default!
      • But eRuby is not only for...
Solution by ERB

  ‣ Nothing for officially
  ‣ Unofficial solution
    • Define a certain class which represents HTML string...
Solution by Erubis

   ‣ Enhance embedded pattern and Erubis class
     • Fast, and easy to implement

   eruby = Erubis::...
Issue : hard to find syntax error
   <% unless @items.blank? %>
   <table>
    <tbody>
      <% @items.each do |item| %>
  ...
Solution by ERB

   ‣ Nothing but '-x' option
   $ erb -x foo.eruby
   _erbout = ''; unless @items.blank? ;
   _erbout.con...
Solution by Erubis

   ‣ Provides a lot of command-line options
     • -x :   show Ruby script
     • -X :   suppress to p...
$ cat foo.eruby
<% unless @items.blank? %>
<table>
 <% @items.each_with_index do|x, i| %>
 <tr class="record">
   <td><%= ...
-x : show Ruby script
$ erubis -x foo.eruby
_buf = ''; unless @items.blank?
 _buf << '<table>
'; @items.each_with_index do...
-X : suppress to print HTML
$ erubis -X foo.eruby
_buf = ''; unless @items.blank?

 @items.each_with_index do|x, i|

     ...
-N : print line numbers
$ erubis -XN foo.eruby
   1: _buf = ''; unless @items.blank?
   2:
   3: @items.each_with_index do...
-U : unifiy consecutive empty
                                                 lines into a line
$ erubis -XNU foo.eruby
  ...
-C : remove empty lines
                                                   (compact)
$ erubis -XNC foo.eruby
   1: _buf = ...
Issue : expr can contain statements

     embed return value of
   helper method by <%= %>
                               ...
Cause of Issue

   <%= 10.times do %>
   Hello                                     <%= expr %> is expected
   <% end %>   ...
Solution by ERB+Rails

   ‣ Change local variable (_erbout) on caller-
     size from callee-side                         ...
Solution by Erubis+Merb

   ‣ Extend parser of Erubis
     Recognize blok in
      embedded expr

<%= form_for do %>      ...
Discussion

   ‣ Extend spec of eRuby
   ‣ Not use black magic (kool!)
   ‣ Available only for helper method, in fact
    ...
Conslusion

   ‣ A lot of issues around eRuby!
     • Extra line breaks
     • Local variables are not local
     • Difficu...
Part 3. Future of template
          system


      copyright(c) 2009 kuwata-lab.com all rights reserved.
                ...
Template and Programming

    ‣ Template is also program code
<ul>                                            print "<ul>n...
Template and Method

      Template is a kind of
       method definition

 <ul>                                 s = File.r...
Template and formal argument

   ‣ Formal arguments may be necessary for
     template

 <%#ARGS: items, name='guest' %>
 ...
Template and modularity
    ‣ Also HTML should be Small & Many, not
      Single & Large
       • Same as principle of met...
Template and Object-Oriented

    ‣ Template inheritance in Django
Parent template
 ....
                                 ...
Template and Aspect-Oriented

   ‣ Weave some code into other program
     • Similar to layer of Photoshop
 <table>
      ...
Template and Data Type

 ‣ End is coming to escape HTML in view layer
   • forget to escape, helper method argument, ...
 ...
Conslusion

   ‣ Template is also programming code
   ‣ Available to apply programming techniques
     and concepts into t...
Bibliography

 ‣ Introduction to Template System (in Japanese)
    • http://jp.rubyist.net/magazine/?0024-TemplateSystem
 ...
one more thing

   copyright(c) 2009 kuwata-lab.com all rights reserved.
                                                 ...
Tenjin - template engine replacing eRuby

 ‣ Both ERB and Erubis are out of date
    • They are merely text-processor
    ...
thank you

 copyright(c) 2009 kuwata-lab.com all rights reserved.
                                                        ...
Upcoming SlideShare
Loading in …5
×

All about Erubis (English)

6,243 views

Published on

(This is presentation slide for RubyKaigi 2009)
Erubis is very fast and extensible implementation of eRuby. In this slides, I show you features of Erubis, and issues related to eRuby and solution by Erubis. Also I show you some ideas about the future of template system.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,243
On SlideShare
0
From Embeds
0
Number of Embeds
22
Actions
Shares
0
Downloads
27
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

All about Erubis (English)

  1. 1. RubyKaigi2009 All about Erubis And the future of template system makoto kuwata <kwa@kuwata-lab.com> http://www.kuwata-lab.com/ copyright(c) 2009 kuwata-lab.com all rights reserved. 1
  2. 2. I have something to say at first... ‣ Thank you for all staff of RubyKaigi! ‣ Thank you for all audience who join this session! copyright(c) 2009 kuwata-lab.com all rights reserved. 2
  3. 3. Agenda ‣ Part 1. Features of Erubis ‣ Part 2.Issues about eRuby and solutions by Erubis ‣ Part 3. Future of template system copyright(c) 2009 kuwata-lab.com all rights reserved. 3
  4. 4. Part 1. Features of Erubis copyright(c) 2009 kuwata-lab.com all rights reserved. 4
  5. 5. Introduction to Erubis ‣ Pure Ruby implementation of eRuby ‣ Very fast • http://jp.rubyist.net/magazine/?0022-FasterThanC ‣ Highly functional • HTML escape in default • Changing embedded pattern • Support PHP, Java, JS, C, Perl, Scheme • and so on... copyright(c) 2009 kuwata-lab.com all rights reserved. 5
  6. 6. Basically Usage Ruby program: require 'rubygems' # if need require 'erubis' str = File.read('template.eruby') eruby = Erubis::Eruby.new(str) print eruby.result(binding()) command-line: $ erubis template.eruby # execute $ erubis -x template.eruby # convert into Ruby $ erubis -z template.eruby # syntax check copyright(c) 2009 kuwata-lab.com all rights reserved. 6
  7. 7. HTML Escape in Default str =<<END <%= %> ... WITH escaping, <%= var %> <%== %> ... WITHOUT escaping <%== var %> END eruby = Erubis::Eruby.new(str, :escape=>true) puts eruby.result(:var=>"<B&B>") output: &lt;B&am;&gt; User can choose escape or not <B&B> escape in default (choosability) copyright(c) 2009 kuwata-lab.com all rights reserved. 7
  8. 8. Changing Embedded Pattern ‣ ex : use '[% %]' instead of '<% %>' [% for x in @list %] <li>[%= x %]</li> You must escape regexp meta [% end %] characters by backslash! ## Ruby Erubis::Eruby.new(str, :pattern=>'[% %]') ## command-line $ erubis -p '[% %]' file.eruby copyright(c) 2009 kuwata-lab.com all rights reserved. 8
  9. 9. Use Hash or Object instead of Binding example of using Hash example of using Object hash = { @title = "Example" :title => "Example", @items = [1, 2, 3] :items => [1, 2, 3], } erubis = erubis = Erubis::Eruby.new(str) Erubis::Eruby.new(str) puts erubis.evaluate(self) puts erubis.result(hash) <h1><%= title%></h1> <h1><%= @title%></h1> <% for x in items %> <% for x in @items %> <% end %> <% end %> copyright(c) 2009 kuwata-lab.com all rights reserved. 9
  10. 10. Enhancer ‣ Ruby modules which enhances Erubis features ## do HTML escape <%= %> in default module EscapeEnhancer def add_expr(src, code, indicator) if indicator == '=' src << " _buf<<escapeXml(#{code})" elsif indicator == '==' src << " _buf<<(#{code}).to_s;" end end It is easy to override Erubis features because internal of Erubis is splitted into end many small methods. copyright(c) 2009 kuwata-lab.com all rights reserved. 10
  11. 11. Enhancer (cont') ### Enhance which prints into stdout ### (you can use print() in statements) module StdoutEnhancer use _buf=$stdout def add_preamble(src) instead of _buf="" src << "_buf = $stdout;" end def add_postamble(src) src << "n""n" end use "" (empty string) end instead of _buf.to_s copyright(c) 2009 kuwata-lab.com all rights reserved. 11
  12. 12. Usage of Enhancer All you have to do is to include ### Ruby or extend ehnacer modules class MyEruby < Erubis::Eruby include Erubis::EscapeEnhancer include Erubis::PercentLineEnhancer end puts MyEruby.new(str).result(:items=>[1,2,3]) Specify names with ',' ### command-line $ erubis -E Escape,Percent file.eruby copyright(c) 2009 kuwata-lab.com all rights reserved. 12
  13. 13. Standard Enhancers ‣ EscapeEnhancer : escape html in default ‣ PercentLineEnhancer : recognize lines starting with '%' as embedded statements ‣ InterporationEnhancer : use _buf<<"#{expr}" for speed ‣ DeleteIndentEnhancer : delete HTML indentation ‣ StdoutEnhancer : use _buf=$stdout instead of _buf="" ‣ ... and so on (you can show list of all by erubis -h) copyright(c) 2009 kuwata-lab.com all rights reserved. 13
  14. 14. Context Data ‣ You can specify data to pass into template file (context data) in command-line ### command-line $ erubis -c '{arr: [A, B, C]}' template.eruby # YAML $ erubis -c '@arr=%w[A B C]' template.eruby # Ruby <% for x in @arr %> <li>A</li> <li><%= x %></li> <li>B</li> <% end %> <li>C</li> copyright(c) 2009 kuwata-lab.com all rights reserved. 14
  15. 15. Context Data File ‣ Load '*.yaml' or '*.rb' as context data file $ erubis -f data.yaml template.eruby # YAML $ erubis -f data.rb template.eruby # Ruby data.yaml data.rb title: Example @title = "Example" items: @items = - name: Foo [ {"name"=>"Foo"}, - name: Bar {"name"=>"Bar"}, ] copyright(c) 2009 kuwata-lab.com all rights reserved. 15
  16. 16. Debug Print ‣ <%=== expr %> represents debug print <%=== @var %> No need to write the same expression twice ### Ruby code $stderr.puts("*** debug: @var=#{@var.inspect}") ### Result *** debug: @var=["A", "B", "C"] copyright(c) 2009 kuwata-lab.com all rights reserved. 16
  17. 17. Support Other Programming Langs ‣ PHP, Java, JS, C, Perl,Scheme (only for convertion) <% for (i=0; i<n; i++) { %> (example of C) <li><%= "%d", i %> <% } %> same format as printf() #line 1 "file.ec" (output of erubis -xl c file.ec) for (i=0; i<n; i++) { fputs("<li>", stdout); fprintf(stdout, "%d", i); fputs("n", stdout); } copyright(c) 2009 kuwata-lab.com all rights reserved. 17
  18. 18. Conslution ‣ Erubis is very functional and extensible • HTML escape in default • Changing embedded pattern • Enhancer • Context data and file • Debug print • Support PHP, Java, JS, C, Perl, and Scheme copyright(c) 2009 kuwata-lab.com all rights reserved. 18
  19. 19. Part 2. Issues about eRuby and solutions by Erubis copyright(c) 2009 kuwata-lab.com all rights reserved. 19
  20. 20. Issue : local variables can be changed ‣ When using binding(), local variables can be non-local • Difficult to find if exists i=0 ### file.erb str = File.read('file.erb') <% for i in 1..3 %> ERB.new(str).result(binding) <li><%= i %></li> p i #=> 3 <% end %> Changed insidiously! copyright(c) 2009 kuwata-lab.com all rights reserved. 20
  21. 21. Cause of the issue ‣ binding() passes all local variables into template file • It is impossible to pass only variables which you truly want to pass • It is hard to recognize what variables are passed b = Bingind.new This is ideal b[:title] = "Example" but impossible... b[:items] = [1, 2, 3] copyright(c) 2009 kuwata-lab.com all rights reserved. 21
  22. 22. Solution by ERB ‣ Nothing, but the author of ERB introduced a solution to define custom Struct • http://d.hatena.ne.jp/m_seki/20080528/1211909590 Foo = Struct.new(:title, :items) class Foo def env; binding(); end end ctx = Foo.new("Example", [1,2,3]) ERB.new(str).result(ctx.env) copyright(c) 2009 kuwata-lab.com all rights reserved. 22
  23. 23. Solution by Erubis ‣ Use Hash instead of Binding It is very clear what erubis.result(:items=>[1, 2, 3]) data are passed! def result(b=TOPLEVEL_BINDING) if b.is_a?(Hash) s = b.collect{|k,v| "#{k}=b[#{k.inspect}];"}.join b = binding() eval s, b Set hash values as local vars end with creating new Binding return eval(@src, b) end copyright(c) 2009 kuwata-lab.com all rights reserved. 23
  24. 24. Solution by Erubis (cont') ‣ Use Object instead of Binding @items = [1, 2, 3]; <% for x in @items %> erubis.evaluate(self) <% end %> def evaluate(ctx) Convert Hash values into if ctx.is_a?(Hash) instance variables hash = ctx; ctx = Object.new hash.each {|k,v| ctx.instance_variable_set("@#{k}", v) } end return ctx.instance_eval(@src) end copyright(c) 2009 kuwata-lab.com all rights reserved. 24
  25. 25. Issue : cost of convertion and parsing ERB 1. 8.6 Erubis::Eruby ERB 1. 8.7 Erubis::Eruby ERB 1.9.1 Erubis::Eruby 0 10 20 30 (sec) Costs of parsing and Execution convertion are higher Parsing(by eval) than of execution Convertion(eRuby to Ruby) copyright(c) 2009 kuwata-lab.com all rights reserved. 25
  26. 26. Solution by ERB ‣ Convertion cost : nothing ‣ Parsing cost : helper to define method • Usage is much different from normal usage class Foo extend ERB::DefMethod def_erb_method('render', 'template.erb') end print Foo.new.render copyright(c) 2009 kuwata-lab.com all rights reserved. 26
  27. 27. Solution by Erubis ‣ Convertion cost : cache Ruby code into file • 1st time : save converted Ruby code into *.cache file • 2nd time : read ruby code from *.cache file eruby = Erubis::Eruby.load_file("file.eruby") print eruby.result() Available even in CGI copyright(c) 2009 kuwata-lab.com all rights reserved. 27
  28. 28. Solution by Erubis (cont') ‣ Parsing cost : keep ruby code as Proc object • The same way to use • Almost the same speed as defining method instance_eval can take a def evaluate(ctx) Proc object as argument @proc ||= eval(@src) instead of string (ruby code) ctx.instance_eval(@proc) end copyright(c) 2009 kuwata-lab.com all rights reserved. 28
  29. 29. Issue: extra line breaks ‣ eRuby outpus extra line breaks • Big problem for non-HTML text Extra line break <ul> <ul> <% for x in @list %> <li>AAA</li> <li><%= x %></li> <% end %> <li>BBB</li> </ul> Extra line break </ul> copyright(c) 2009 kuwata-lab.com all rights reserved. 29
  30. 30. Solution by ERB ‣ Provides various trim mode • ">" : removes LF at the end of line • "<>" : removes LF if "<%" is at the beginning of line and "%>" is at the end of line • "-" : removes extra spaces and LF around "<%-" and "-%>" • "%" : regard lines starting with "%" as embedded statements • "%>", "%<>", "-" : combination of "%" and ">"/"<>"/"-" ERB.new(str, nil, "%<>") copyright(c) 2009 kuwata-lab.com all rights reserved. 30
  31. 31. Solution by Erubis ‣ Change operation between embedded statement and expression • <% stmt %> : remove spaces around it • <%= expr %> : do nothing (leave as it is) <ul> Remove! <ul> <% for x in @list %> AAA <%= x %> BBB <% end %> CCC </ul> Leave as it is </ul> copyright(c) 2009 kuwata-lab.com all rights reserved. 31
  32. 32. Comparison of solutions ERB Erubis eRuby spec compatible × spec) (compatible) (extends Spec simplicity × opts) (only one rule) (too much Easy to implement × (very easy) (complicated) copyright(c) 2009 kuwata-lab.com all rights reserved. 32
  33. 33. Hint to think ‣ "Extra line breaks" problem has been recognized since early times • [ruby-list:18894] extra LF in output of eRuby ‣ Nobody hit on the idea of changing operations between stmts and exprs • Everybody looks <% %> and <%= %> as same • It is important to recoginize two things which looks to be the same things as different things copyright(c) 2009 kuwata-lab.com all rights reserved. 33
  34. 34. Issue : Escape HTML in default ‣ <%= expr %> should be HTML escaped in default! • But eRuby is not only for HTML but also for all of text file • However security is the most important thing ‣ How to do when not to escape? copyright(c) 2009 kuwata-lab.com all rights reserved. 34
  35. 35. Solution by ERB ‣ Nothing for officially ‣ Unofficial solution • Define a certain class which represents HTML string (not to escape) separately from String class • http://www2a.biglobe.ne.jp/~seki/ruby/erbquote.html copyright(c) 2009 kuwata-lab.com all rights reserved. 35
  36. 36. Solution by Erubis ‣ Enhance embedded pattern and Erubis class • Fast, and easy to implement eruby = Erubis::Eruby.new(str, :escape=>true) # or eruby = Erubis::EscapedEruby.new(str) puts eruby.evaluate(ctx) Hi <%= @name %>! # with escape Hi <%== @name %>! # without escape copyright(c) 2009 kuwata-lab.com all rights reserved. 36
  37. 37. Issue : hard to find syntax error <% unless @items.blank? %> <table> <tbody> <% @items.each do |item| %> <tr class="item" id="item-<%=item.id%>"> <td class="item-id"><%= item.id %></td> <td class="item-name"> <% if item.url && !item.url.empty? %> <a href="<%= item.url %>"><%=item.name%></a> <% else %> <span><%=item.name%></span> <% end %> </td> </tr> • HTML and Ruby code are mixed <% end %> • It is hard to recognize corresponding </tbody> </table> 'end' (because 'do' and 'end' can be <% end %> separated 100 lines for example) copyright(c) 2009 kuwata-lab.com all rights reserved. 37
  38. 38. Solution by ERB ‣ Nothing but '-x' option $ erb -x foo.eruby _erbout = ''; unless @items.blank? ; _erbout.concat "n" _erbout.concat "<table>n" _erbout.concat " <tr class="record">n" $ erb -x foo.eruby | ruby -wc Syntax OK copyright(c) 2009 kuwata-lab.com all rights reserved. 38
  39. 39. Solution by Erubis ‣ Provides a lot of command-line options • -x : show Ruby script • -X : suppress to print HTML • -N : print line numbers • -U : unify consecutive empty lines into a line • -C : remove consecutive empty lines (compact) • -z : check template syntax copyright(c) 2009 kuwata-lab.com all rights reserved. 39
  40. 40. $ cat foo.eruby <% unless @items.blank? %> <table> <% @items.each_with_index do|x, i| %> <tr class="record"> <td><%= i +1 %></td> <td><%=h x %></td> </tr> <% end %> </table> <% end %> copyright(c) 2009 kuwata-lab.com all rights reserved. 40
  41. 41. -x : show Ruby script $ erubis -x foo.eruby _buf = ''; unless @items.blank? _buf << '<table> '; @items.each_with_index do|x, i| _buf << ' <tr class="record"> <td>'; _buf << ( i +1 ).to_s; _buf << '</td> <td>'; _buf << (h x ).to_s; _buf << '</td> </tr> '; end _buf << '</table> '; end _buf.to_s copyright(c) 2009 kuwata-lab.com all rights reserved. 41
  42. 42. -X : suppress to print HTML $ erubis -X foo.eruby _buf = ''; unless @items.blank? @items.each_with_index do|x, i| _buf << ( i +1 ).to_s; _buf << (h x ).to_s; end end _buf.to_s copyright(c) 2009 kuwata-lab.com all rights reserved. 42
  43. 43. -N : print line numbers $ erubis -XN foo.eruby 1: _buf = ''; unless @items.blank? 2: 3: @items.each_with_index do|x, i| 4: 5: _buf << ( i +1 ).to_s; 6: _buf << (h x ).to_s; 7: 8: end 9: 10: end 11: _buf.to_s copyright(c) 2009 kuwata-lab.com all rights reserved. 43
  44. 44. -U : unifiy consecutive empty lines into a line $ erubis -XNU foo.eruby 1: _buf = ''; unless @items.blank? 3: @items.each_with_index do|x, i| 5: _buf << ( i +1 ).to_s; 6: _buf << (h x ).to_s; 8: end 10: end 11: _buf.to_s copyright(c) 2009 kuwata-lab.com all rights reserved. 44
  45. 45. -C : remove empty lines (compact) $ erubis -XNC foo.eruby 1: _buf = ''; unless @items.blank? 3: @items.each_with_index do|x, i| 5: _buf << ( i +1 ).to_s; 6: _buf << (h x ).to_s; 8: end 10: end 11: _buf.to_s copyright(c) 2009 kuwata-lab.com all rights reserved. 45
  46. 46. Issue : expr can contain statements embed return value of helper method by <%= %> block contains statements <%= form_for :user do %> <div> <%= text_field :name %> </div> <% end %> beyond of eRuby spec! copyright(c) 2009 kuwata-lab.com all rights reserved. 46
  47. 47. Cause of Issue <%= 10.times do %> Hello <%= expr %> is expected <% end %> to be completed by itself Convert Syntax error! _buf = ""; _buf << ( 10.times do ).to_s; _buf << " Hellon"; end copyright(c) 2009 kuwata-lab.com all rights reserved. 47
  48. 48. Solution by ERB+Rails ‣ Change local variable (_erbout) on caller- size from callee-side agic!! b lack m Append to '_erbout' from Not use <%= %> internal of form_for() <% form_for do %> _erbout = "" Hello form_for do <% end %> _erbout.concat("Hello") end copyright(c) 2009 kuwata-lab.com all rights reserved. 48
  49. 49. Solution by Erubis+Merb ‣ Extend parser of Erubis Recognize blok in embedded expr <%= form_for do %> @_buf << (form_for do; Hello @_buf << "Hellon" <% end =%> end); Introduce end-of- Change _buf into block notation instance variable copyright(c) 2009 kuwata-lab.com all rights reserved. 49
  50. 50. Discussion ‣ Extend spec of eRuby ‣ Not use black magic (kool!) ‣ Available only for helper method, in fact • It is required to manipulate @_buf from internal of helper method ‣ Difficult to provide general solution copyright(c) 2009 kuwata-lab.com all rights reserved. 50
  51. 51. Conslusion ‣ A lot of issues around eRuby! • Extra line breaks • Local variables are not local • Difficult to specify context variable • Large cost for convertion and parsing • HTML escape in default • Difficult to find syntax error • Can't embed return value of method with block copyright(c) 2009 kuwata-lab.com all rights reserved. 51
  52. 52. Part 3. Future of template system copyright(c) 2009 kuwata-lab.com all rights reserved. 52
  53. 53. Template and Programming ‣ Template is also program code <ul> print "<ul>n" <% for x in @a %> for x in @a <li><%=x%></li> Equiv. print "<li>#{x}</li>n" <% end %> end </ul> print "</u>n" Possible to apply programming techniques or concepts to template system copyright(c) 2009 kuwata-lab.com all rights reserved. 53
  54. 54. Template and Method Template is a kind of method definition <ul> s = File.read('foo.eruby') <li><%=x%></li> e = Erubis::Eruby.new(s) </ul> puts e.evaluate(:x=>1) Context data is actual Rendering template is a argument for method kind of method invokation copyright(c) 2009 kuwata-lab.com all rights reserved. 54
  55. 55. Template and formal argument ‣ Formal arguments may be necessary for template <%#ARGS: items, name='guest' %> Hello <%= name %>! <% for x in items %> <li><%=x%></li> • Clear context variables <% end %> • Available default value copyright(c) 2009 kuwata-lab.com all rights reserved. 55
  56. 56. Template and modularity ‣ Also HTML should be Small & Many, not Single & Large • Same as principle of method definition <html> <html> Be benefit for <body> designer! <body> </body> <h1><%=@title%></h1> </html> <ul id="menulist"> split <% for x in @items %> <h1><%=@title%></h1> <li><%=x%></li> <ul id="menulist"> </ul> <% end %> </ul> <% for x in @items %> </body> <li><%= x %></li> </html> <% end %> copyright(c) 2009 kuwata-lab.com all rights reserved. 56
  57. 57. Template and Object-Oriented ‣ Template inheritance in Django Parent template .... Available to overwrite {% block pagetitle %} or add contents <h1>{{title}}</h1> before/after {% endblock %} (method override) .... copyright(c) 2009 kuwata-lab.com all rights reserved. 57
  58. 58. Template and Aspect-Oriented ‣ Weave some code into other program • Similar to layer of Photoshop <table> "for x in @a" •Enable to split HTML <tr> and presentation <td> "print x" logics •Available to insert a </tr> logic into several "end" points (DRY) </table> copyright(c) 2009 kuwata-lab.com all rights reserved. 58
  59. 59. Template and Data Type ‣ End is coming to escape HTML in view layer • forget to escape, helper method argument, ... ‣ HTML should be different data type from String (http://www.oiwa.jp/~yutaka/tdiary/20051229.html) • No need to take care to escape or not • Prior art : str and unicode in Python • "HTML + String" should be String? or HTML? • Other escaping also should be considered (ex. SQL) copyright(c) 2009 kuwata-lab.com all rights reserved. 59
  60. 60. Conslusion ‣ Template is also programming code ‣ Available to apply programming techniques and concepts into template system • Formal argument, Inheritance, AOP, and so on ‣ Template system is still on developing stage copyright(c) 2009 kuwata-lab.com all rights reserved. 60
  61. 61. Bibliography ‣ Introduction to Template System (in Japanese) • http://jp.rubyist.net/magazine/?0024-TemplateSystem • http://jp.rubyist.net/magazine/?0024-TemplateSystem2 ‣ Erubis • http://www.kuwata-lab.com/erubis/ ‣ Benchmarks of many template systems • http://www.kuwata-lab.com/tenjin/ copyright(c) 2009 kuwata-lab.com all rights reserved. 61
  62. 62. one more thing copyright(c) 2009 kuwata-lab.com all rights reserved. 62
  63. 63. Tenjin - template engine replacing eRuby ‣ Both ERB and Erubis are out of date • They are merely text-processor • Less features as template engine ‣ Tenjin : replacer of ERB/Erubis • Designed and implemented as template engine from the beginning • Provides a lot of features required for template engines - layout template, partial template, and so on • http://www.kuwata-lab.com/tenjin/ copyright(c) 2009 kuwata-lab.com all rights reserved. 63
  64. 64. thank you copyright(c) 2009 kuwata-lab.com all rights reserved. 64

×