SlideShare a Scribd company logo
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
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
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
Part 1. Features of Erubis



      copyright(c) 2009 kuwata-lab.com all rights reserved.
                                                              4
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Part 2. Issues about eRuby
 and solutions by Erubis


      copyright(c) 2009 kuwata-lab.com all rights reserved.
                                                              19
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
$ 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
-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
-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
-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
-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
-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
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
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
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
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
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
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
Part 3. Future of template
          system


      copyright(c) 2009 kuwata-lab.com all rights reserved.
                                                              52
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
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
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
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
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
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
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
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
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
one more thing

   copyright(c) 2009 kuwata-lab.com all rights reserved.
                                                           62
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
thank you

 copyright(c) 2009 kuwata-lab.com all rights reserved.
                                                         64

More Related Content

What's hot

Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner) Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Puppet
 
Python高级编程(二)
Python高级编程(二)Python高级编程(二)
Python高级编程(二)
Qiangning Hong
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
Nikita Popov
 
Advanced python
Advanced pythonAdvanced python
Advanced pythonEU Edge
 
Letswift19-clean-architecture
Letswift19-clean-architectureLetswift19-clean-architecture
Letswift19-clean-architecture
Jung Kim
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.VimLin Yo-An
 
Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)
Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)
Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)
Uri Laserson
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
Nikita Popov
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim Perlchinaguestcf9240
 
Ruby 2.0
Ruby 2.0Ruby 2.0
Ruby 2.0
Uģis Ozols
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
Mark Baker
 
I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On Rails
John Wilker
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaLin Yo-An
 
Good Evils In Perl
Good Evils In PerlGood Evils In Perl
Good Evils In PerlKang-min Liu
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
Patrick Allaert
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)
Nikita Popov
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Kris Wallsmith
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
Han Lee
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)
David de Boer
 
Ow2 webinar erocci
Ow2 webinar erocciOw2 webinar erocci
Ow2 webinar erocci
Jean Parpaillon
 

What's hot (20)

Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner) Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
 
Python高级编程(二)
Python高级编程(二)Python高级编程(二)
Python高级编程(二)
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
 
Advanced python
Advanced pythonAdvanced python
Advanced python
 
Letswift19-clean-architecture
Letswift19-clean-architectureLetswift19-clean-architecture
Letswift19-clean-architecture
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
 
Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)
Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)
Numba-compiled Python UDFs for Impala (Impala Meetup 5/20/14)
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim Perlchina
 
Ruby 2.0
Ruby 2.0Ruby 2.0
Ruby 2.0
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On Rails
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim Perlchina
 
Good Evils In Perl
Good Evils In PerlGood Evils In Perl
Good Evils In Perl
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)
 
Ow2 webinar erocci
Ow2 webinar erocciOw2 webinar erocci
Ow2 webinar erocci
 

Similar to All about Erubis (English)

JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011Nick Sieger
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
Hiroshi SHIBATA
 
Connecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyConnecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRuby
Nick Sieger
 
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret SauceHiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Jesse Vincent
 
New features in Ruby 2.5
New features in Ruby 2.5New features in Ruby 2.5
New features in Ruby 2.5
Ireneusz Skrobiś
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
Marc Chung
 
Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...
Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...
Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...
Amazon Web Services
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
sickill
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
Daniel Spector
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
Michael MacDonald
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails Introduction
Thomas Fuchs
 
Php classes in mumbai
Php classes in mumbaiPhp classes in mumbai
Php classes in mumbai
aadi Surve
 
C++ Core Guidelines
C++ Core GuidelinesC++ Core Guidelines
C++ Core Guidelines
Thomas Pollak
 
How to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHow to Begin to Develop Ruby Core
How to Begin to Develop Ruby Core
Hiroshi SHIBATA
 
Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)
Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)
Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)Muhamad Al Imran
 
Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)
Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)
Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)Muhamad Al Imran
 

Similar to All about Erubis (English) (20)

JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
 
Connecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyConnecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRuby
 
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret SauceHiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
 
Gun make
Gun makeGun make
Gun make
 
New features in Ruby 2.5
New features in Ruby 2.5New features in Ruby 2.5
New features in Ruby 2.5
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
 
Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...
Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...
Distributed, Incremental Dataflow Processing on AWS with GRAIL's Reflow (CMP3...
 
lab4_php
lab4_phplab4_php
lab4_php
 
lab4_php
lab4_phplab4_php
lab4_php
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails Introduction
 
Php classes in mumbai
Php classes in mumbaiPhp classes in mumbai
Php classes in mumbai
 
C++ Core Guidelines
C++ Core GuidelinesC++ Core Guidelines
C++ Core Guidelines
 
How to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHow to Begin to Develop Ruby Core
How to Begin to Develop Ruby Core
 
Php i basic chapter 3
Php i basic chapter 3Php i basic chapter 3
Php i basic chapter 3
 
Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)
Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)
Php i basic chapter 3 (syahir chaer's conflicted copy 2013-04-22)
 
Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)
Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)
Php i basic chapter 3 (afifah rosli's conflicted copy 2013-04-23)
 

More from kwatch

How to make the fastest Router in Python
How to make the fastest Router in PythonHow to make the fastest Router in Python
How to make the fastest Router in Python
kwatch
 
Migr8.rb チュートリアル
Migr8.rb チュートリアルMigr8.rb チュートリアル
Migr8.rb チュートリアル
kwatch
 
なんでもID
なんでもIDなんでもID
なんでもID
kwatch
 
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
kwatch
 
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
kwatch
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
kwatch
 
正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?
kwatch
 
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
kwatch
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
kwatch
 
PHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較するPHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較する
kwatch
 
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
kwatch
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
kwatch
 
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
kwatch
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門
kwatch
 
Pretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/MercurialPretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/Mercurial
kwatch
 
Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -
kwatch
 
文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた
kwatch
 
I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"kwatch
 
Javaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジンJavaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジン
kwatch
 
Underlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R MapperUnderlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R Mapper
kwatch
 

More from kwatch (20)

How to make the fastest Router in Python
How to make the fastest Router in PythonHow to make the fastest Router in Python
How to make the fastest Router in Python
 
Migr8.rb チュートリアル
Migr8.rb チュートリアルMigr8.rb チュートリアル
Migr8.rb チュートリアル
 
なんでもID
なんでもIDなんでもID
なんでもID
 
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
 
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
 
正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?
 
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
PHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較するPHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較する
 
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
 
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門
 
Pretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/MercurialPretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/Mercurial
 
Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -
 
文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた
 
I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"
 
Javaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジンJavaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジン
 
Underlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R MapperUnderlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R Mapper
 

Recently uploaded

GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 

Recently uploaded (20)

GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 

All about Erubis (English)

  • 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. 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. 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. Part 1. Features of Erubis copyright(c) 2009 kuwata-lab.com all rights reserved. 4
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Part 2. Issues about eRuby and solutions by Erubis copyright(c) 2009 kuwata-lab.com all rights reserved. 19
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. $ 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. -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. -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. -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. -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. -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. 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. 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. 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. 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. 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. 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. Part 3. Future of template system copyright(c) 2009 kuwata-lab.com all rights reserved. 52
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. one more thing copyright(c) 2009 kuwata-lab.com all rights reserved. 62
  • 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. thank you copyright(c) 2009 kuwata-lab.com all rights reserved. 64