[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
SlideShare a Scribd company logo
RubyKaigi 2010




HTMLデザインを崩さない
テンプレートエンジンの作り方
                                                      makoto kuwata
                                          http://www.kuwata-lab.com/




     English ver: http://slidesha.re/a3s2ZZ

     copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                              1
はじめに

目的
       ✤   テンプレートエンジン利用者に、正しい
           知識を理解してもらう
       ✤   テンプレートエンジン設計者に、あるべ
           き姿を考えてもらう

動機     ✤   間違った説明が蔓延しており是正したい
       ✤   eRubyは決して理想解ではないことを
           知ってほしい

対象者    ✤   テンプレートエンジンの利用者と設計者


            copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                    2
お詫び
✤   今日話したかったこと
    ✤   テンプレートのデザインを崩さない方法について
    ✤   テンプレートエンジンの高速化について
    ✤   既存のテンプレートエンジンが抱える問題点について
    ✤   デザインを崩さず、高速で、どの言語でも比較的簡単に
        実装できるテンプレートエンジンの作り方について

✤   30分しかないので最初の項目だけ
    ✤   野心的すぎました、ごめんなさい

               copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                       3
参考文献
✤   Rubyist Magazine - テンプレートシステム入門
    ✤   http://jp.rubyist.net/magazine/?0024-TemplateSystem
    ✤   http://jp.rubyist.net/magazine/?0024-TemplateSystem2




                      copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                              4
アジェンダ
✤   基礎知識編
    ✤   ビジネス層とプレゼンテーション層
    ✤   現状の問題点とその原因
    ✤   プレゼンテーションロジック

✤   Kwartz編
    ✤   はじめてのKwartz入門
    ✤   プレゼンテーションパターン


                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        5
基礎知識編:
ビジネス層とプレゼンテーション層




         copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                 6
ビジネス層とプレゼンテーション層
✤   ビジネス層
    ✤   役割:「何を(what)表示するか?」を決定
    ✤   担当:メインプログラム

✤   プレゼンテーション層
    ✤   役割:「どのように(how)表示するか?」を決定
    ✤   担当:テンプレートファイルおよびエンジン




                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        7
データとロジック
✤   ビジネス層とプレゼンテーション層の両方に、
    データとロジックが存在
             ビジネス層                                   プレゼンテーション層
            (メインプログラム)                                (テンプレートエンジン)

                                                       プレゼンテーション
     データ    ビジネスデータ
                                                                     データ
                                                       プレゼンテーション
     ロジック   ビジネスロジック
                                                                     ロジック

            テンプレートエンジンはここを分離
             copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                            8
具体例
                                                         ビジネスデータ
✤   営業部員の売上成績から
                                                       ビジネスロジック
✤   上位 20 名を選出し、

✤   奇数行と偶数行で背景色を変えて
                                                                   プレゼンテー
✤   <table> タグで表示する                                                ションロジック

                         プレゼンテー
                         ションデータ


           copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                             9
よくある間違い(1)

(誤)   ✤   テンプレートエンジンは、ロジックと
          プレゼンテーションを分離する
      ✤   テンプレートエンジンは、ビジネス層
(正)
          とプレゼンテーション層を分離する
          ✤   プレゼンテーション層にもロジックがある




                                               自分も昔は間違ってました…
                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        10
よくある間違い(2)

(誤)   ✤   プレゼンテーション層にはロジックを
          含めるべきではない
      ✤   プレゼンテーション層はプレゼンテー
(正)
          ションロジックを含む
          ✤   「HTMLテンプレートにプレゼンテーション
              ロジックを含めない」ことと、「ビジネス層
              とプレゼンテーション層を分離する」こと
              は、別の話



                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        11
ここまでのまとめ
✤   ビジネス層
    ✤   何を(What)表示するか?
    ✤   メインプログラムが担当

✤   プレゼンテーション層
    ✤   どう(How)表示するか?
    ✤   テンプレートファイルが担当

✤   どちらにもデータとロジックが存在

                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        12
基礎知識編:
現状の問題点とその原因




         copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                 13
デザイナ泣かせの現状
       ProjectA: Rails
<table>                                                             ProjectC: PHP
<%	 @arr.each	 {	 %>                                         <table>
	 	 ....                                                     <?php	 foreach()	 {	 ?>
<%	 }	 %>                                                    	 	 ....
</table>                                                     <?php	 }	 ?>
                                                             </table>
            ProjectB: JSP
     <table>
     <forEach	 items="">                                         プログラマの都合を
     	 	 ....                                                    デザイナに押し付け
     </forEach>                                                  ているのが現状
     </table>
                 copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                       14
共同作業での問題
        テンプレートファイル
        <table>
        <%	 @arr.each	 {	 %>
        	 	 ....
        <%	 }	 %>
        </table>
                       衝突!
                                                          プレゼンテーション
 HTMLを編集                                                  ロジックを編集


 デザイナ                                                              プログラマ

           copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                           15
問題の原因

✤   テンプレート中にプレ                                       テンプレートファイル
    ゼンテーションロジッ                               <table>
    クを埋め込んでいるこ                               <%	 i	 =	 0	 %>
                                             <%	 @arr.eachx	 do	 |x|	 %>
    とこそが、諸悪の根源
                                             <%	 	 	 i	 +=	 i	 %>
                                             <%	 	 	 c	 =	 i.odd	 ?	 	 %>
                                             <%	 	 	 	 	 	 	 'odd':'even'	 %>
    pure HTML テンプ                            	 	 <tr	 class="<%=c%>">
    レートが望ましい                                 	 	 	 	 <td><%=	 x	 %></td>
                                             	 	 </tr>
                                             <%	 end	 %>
                                             </table>

              copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                16
pure HTML テンプレートの利点
              ✤   HTMLデザインが崩れない(表示確認できる)
デザイナ
        for


              ✤   テンプレート言語を学習しなくてよい
              ✤   HTML Validator でチェックできる
              ✤   好きなエディタ (Dreamweaverなど) が使える


                  同時編集による衝突を避けやすい
プログラマ
        for




              ✤


              ✤   空白除去による圧縮(転送量削減)がしやすい
              ✤   ケータイ用などに自動変換しやすい

                       copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                               17
Matzも悩んだ問題
✤   じゃあプレゼンテーションロジックは
    どこに書けばいいの?

    Matz日記 (2004-08-24)
    http://www.rubyist.net/ matz/20040824.html#p01

      (要約)
      ViewそのものにLogicが必要な場合、
      HTMLテンプレートでは記述できないし、
      どこに所属すべきだろうか?


                   copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                           18
ここまでのまとめ
✤   テンプレート中にプレゼンテーションロ
    ジックを埋め込むと、問題が多い
✤   pure HTMLテンプレートが望ましい
✤   プレゼンテーションロジックはどこに?




           copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                   19
基礎知識編:
プレゼンテーションロジック




         copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                 20
プレゼンテーションロジックをどこに?

A. テンプレートファイル中 (eRuby, JSP, Kid)
  プレゼンテーションロジック
                                                    ビジネスロジック&データ
  +プレゼンテーションデータ


B. メインプログラム中 (Amrita2, XMLC, HTML::Template)
                                                 プレゼンテーションロジック
   プレゼンテーションデータ
                                                 +ビジネスロジック&データ


C. 独立した別ファイル中 (Kwartz, Tapestry, Mayaa)
   プレゼンテーションロジック
                                                    ビジネスロジック&データ
   プレゼンテーションデータ

                                         テンプレート                      メインプログラム
             copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                21
A. テンプレートファイル中に記述 (1)

 例: eRuby ファイル (Ruby)
 <table>
 <%	 odd	 =	 false	 %>
 <%	 for	 item	 in	 @list	 %>
 <%	 	 	 odd	 =	 !	 odd
 <%	 	 	 cls	 =	 odd	 ?	 'odd'	 :	 'even'	 %>
 	 	 <tr	 class="<%=	 cls	 %>">
 	 	 	 	 <td><%=h	 item	 %></td>
 	 	 </tr>
                                       •HTMLの中にHTML
 <%	 end	 %>
                                        でないものが混在
 </table>
                                                             →pure HTML でない


                 copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                              22
A. テンプレートファイル中に記述 (2)

 例: JSP ファイル (Java)
 <table>
 	 <c:forEach	 var="item"	 items="${list}"
 	 	 	 	 	 	 	 	 	 	 	 	 varStatus="loop">
 	 	 <c:set	 var="klass"
 	 	 	 	 	 value="${loop.count%2==0?'odd':'even'}"	 />
 	 	 <tr	 class="${klass}">
 	 	 	 	 <td><c:out	 value="${item}"	 /></td>
 	 	 </tr>
 	 </c:forEach>                •カスタムタグを使おうが、ロジックを
 </table>                       テンプレートファイル中に埋め込んで
                           いるという点ではeRubyと同じ

                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        23
A. テンプレートファイル中に記述 (3)

 例: Kid テンプレートファイル (Python)
 <table>
 	 	 <tr	 py:for="i,	 item	 in	 enumerate(items)"
 	 	 	 	 	 	 class="${i	 %	 2	 and	 'even'	 or	 'odd'}">
 	 	 	 	 <td	 py:content="item">dummy</td>
 	 	 </tr>
 </table>
                          •文書構造と属性を使うことで、
                           HTMLデザインを崩さないよう配慮
                          •ロジックをテンプレートファイル中に
                           埋め込んでいるという点では同じ


                   copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                           24
A. テンプレートファイル中に記述 (4)
        プレゼンテーション層(=テンプレート)が
利
    ✤

        ビジネス層から分離されている
点   ✤   使い方がわかりやすく、実装も簡単


        pure HTML でない(ことが多い)
欠
    ✤


    ✤   同時編集による衝突が発生しやすい
点   ✤   デザイナがプレゼンテーションロジックを
        誤って変更する可能性がある



            copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                    25
プレゼンテーションロジックをどこに?

A. テンプレートファイル中 (eRuby, JSP, Kid)
  プレゼンテーションロジック
                                                    ビジネスロジック&データ
  +プレゼンテーションデータ


B. メインプログラム中 (Amrita2, XMLC, HTML::Template)
                                                 プレゼンテーションロジック
   プレゼンテーションデータ
                                                 +ビジネスロジック&データ


C. 独立した別ファイル中 (Kwartz, Tapestry, Mayaa)
   プレゼンテーションロジック
                                                    ビジネスロジック&データ
   プレゼンテーションデータ

                                         テンプレート                      メインプログラム
             copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                26
B. メインプログラム中に記述 (1)

 例: Amrita2 テンプレートファイル (Ruby)
 <table>
 	 	 <tr	 id="list"	 class="odd">
 	 	 	 	 <td	 id="item">dummy</td>
 	 	 </tr>
 </table>

            •書き換えたい場所に「目印」を書くだけ
             (Amrita2ならid属性をつけるだけ)
            •テンプレートが pure HTML (ロジック
             を埋め込まないため)



              copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                      27
B. メインプログラム中に記述 (2)
 例: Amrita2 メインプログラム (Ruby)
 ##	 表示したいビジネスデータ
 list	 =	 [	 'A',	 'B',	 'C'	 ]        •ビジネスデータをプレゼ
 ##	 プレゼンテーションロジック                       ンテーションロジックで
 list2	 =	 [];	 	 odd	 =	 false          加工する必要がある
 for	 x	 in	 list
 	 	 cls	 =	 (odd	 =	 !odd)	 ?	 'odd'	 :	 'even'
 	 	 item2	 =	 a(:class=>cls)	 {	 {:item=>x}	 }
 	 	 list2	 <<	 item2
 end
 context	 =	 {	 :list=>list2	 }
 ##	 テンプレートを読み込んで表示
 tmpl	 =	 Amrita2::TemplateFile.new('ex1.html')
 tmpl.expand(html='',	 context)
 print	 html
                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        28
B. メインプログラム中に記述 (3)
        テンプレートには目印を埋め込むだけ
利
    ✤



        pure HTML テンプレートを実現 (しやすい)
点
    ✤


    ✤   同じファイルを編集しないので衝突しない
    ✤   デザイナによるロジックの誤変更がない

        ビジネス層とプレゼンテーション層が分離で
欠
    ✤


        きてない(*注)
点   ✤   使い方にクセがある(ロジックをデータで表
        現する必要があるため)

             (*注) 工夫次第で回避可能(該当箇所を別クラスにする等)
            copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                    29
プレゼンテーションロジックをどこに?

A. テンプレートファイル中 (eRuby, JSP, Kid)
  プレゼンテーションロジック
                                                    ビジネスロジック&データ
  +プレゼンテーションデータ


B. メインプログラム中 (Amrita2, XMLC, HTML::Template)
                                                 プレゼンテーションロジック
   プレゼンテーションデータ
                                                 +ビジネスロジック&データ


C. 独立した別ファイル中 (Kwartz, Tapestry, Mayaa)
   プレゼンテーションロジック
                                                    ビジネスロジック&データ
   プレゼンテーションデータ

                                         テンプレート                      メインプログラム
             copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                30
C. 独立した別ファイル中に記述 (1)

 例: Kwartz プレゼンテーションデータファイル (Ruby)
 <table>
 	 	 <tr	 id="mark:list"	 class="odd">
 	 	 	 	 <td	 id="mark:item">dummy</td>
 	 	 </tr>
 </table>
           •書き換えたい場所に「目印」を書くだけ
           (Kwartzならid属性をつけるだけ)




            copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                    31
C. 独立した別ファイル中に記述 (2)

 例: Kwartz プレゼンテーションロジックファイル (Ruby)
 #item	 {	 	 	 	 	 	 	 	 	 	 ##	 id="mark:item"	 は
 	 	 value:	 x;	 	 	 	 	 	 ##	 x	 の値を表示する
 }
 #list	 {	 	 	 	 	 	 	 	 	 	 ##	 id="mark:list"	 は
 	 	 logic:	 {	 	 	 	 	 	 	 ##	 要素全体をループする
 	 	 	 	 for	 x	 in	 @list
 	 	 	 	 	 	 _elem
 	 	 	 	 end
 	 	 }                         •あたかもCSSのようにプレゼンテー
 }                              ションロジックを記述する
                          •プレゼンテーションロジックがメイ
                             ンプログラム中に現れない!
               copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                       32
CSS
                   (Visual Design)




                           HTML
                         (Document
                         Structure)
 Kwartz                                                            JavaScript
(Presentation                                                           (Client-side
    Logic)                                                                 Logic)


                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                       33
C. 独立した別ファイル中に記述 (3)
    ✤   ビジネス層とプレゼンテーション層がきれい
利       に分離
点   ✤   プレゼンテーションデータ(HTML)とプレ
        ゼンテーションロジックもきれいに分離
    ✤   pure HTML テンプレートを実現
    ✤   編集するファイルが別なので衝突しない
    ✤   デザイナによるロジックの誤変更がない


欠   ✤   ファイル数が増える
点           copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                    34
大事なことと本当に大事なこと
✤   大事なこと
    ✤   テンプレートが pure HTML であること

✤   本当に大事なこと
    ✤   プレゼンテーションロジックを分離・独立させること
    ✤   (pure HTML はその副産物にすぎない)




                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        35
よくある間違い(1)

(誤)   ✤   テンプレートがpure HTMLなので、
          プレゼンテーション層を分離できてい
          ます!
      ✤   pure HTMLであることと、各層が分
(正)
          離できることは、別個のお話
          ✤   恐らく、HTMLファイル中にロジックが現れ
              ないことを「プレゼンテーション層の分離」
              と勘違いしている



                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        36
よくある間違い(2)

(誤)   ✤   生PHPだとデザイナが変なロジックを
          埋め込む可能性があるので、Smarty
          を導入しました!
      ✤   Smartyではデザイナによる誤変更は防
(正)
          止できない
          ✤   デザイナがプレゼンテーションロジックにア
              クセスできる時点で間違い
          ✤   根本的な解決法は、プレゼンテーションロ
              ジックを分離すること

                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        37
ここまでのまとめ
✤   プレゼンテーションロジックの記述場所
    ✤   テンプレートファイル中(デザイン崩れ、競合が発生)
    ✤   メインプログラム中(分離がいまいち)
    ✤   独立した別ファイル中(いちばん理想的)

✤   pure HTML テンプレートは重要
✤   プレゼンテーションロジックの分離・独立
    はもっと重要

               copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                       38
Kwartz編:
はじめてのKwartz入門




           copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                   39
Kwartz 概要
✤   Kwartzとは?
    ✤   プレゼンテーションデータ(HTML)と
        プレゼンテーションロジックを分離できるテンプレー
        トエンジン
    ✤   pure HTML テンプレート
    ✤   Ruby実装とPHP実装を用意
    ✤   http://www.kuwata-lab.com/kwartz/




                     copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                             40
サンプル: プレゼンテーションデータ

                              書き換えたい箇所に、目印
ex.html                       となるid属性をつける
 <table>
 	 	 <tr	 id="mark:list">
 	 	 	 	 <td	 id="mark:item">Foo</td>
 	 	 </tr>
 	 	 <tr	 id="dummy:d1">
 	 	 	 	 <td>Bar</td>
 	 	 </tr>
 </table>                  「id="dummy:xxx"」は
                                  ダミー要素を表す



                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        41
サンプル: プレゼンテーションロジック

ex.plogic                  id属性ごとにプレゼンテー
 #list	 {                  ションロジックを記述
 	 	 logic:	 {
 	 	 	 	 for	 x	 in	 @list
 	 	 	 	 	 	 _stag	 	 	 	 ##	 開始タグ
 	 	 	 	 	 	 _cont	 	 	 	 ##	 内容
 	 	 	 	 	 	 _etag	 	 	 	 ##	 終了タグ
 	 	 	 	 end
 	 	 }                   <tr>要素を繰り返し
 }
 #item	 {
 	 	 value:	 x;
 }                          <td>要素に値を出力
                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        42
サンプル: コンパイル

eRubyファイルへコンパイル
 $	 kwartz	 -l	 eruby	 -p	 ex.plogic	 ex.html	 >	 ex.rhtml

ex.rhtml (コンパイル結果)
 <table>
 <%	 	 	 	 	 for	 x	 in	 @list	 %>
 	 	 <tr>
 	 	 	 	 <td><%=	 x	 %></td>                        •属性「id="mark:xxx"」は
 	 	 </tr>                                             コンパイル時に削除される
 <%	 	 	 	 	 end	 %>                                   (id="xxx" なら削除されない)
 </table>                                           •「id="dummy:xxx"」は要素
                                                       そのものが削除される
                      copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                              43
サンプル: メインプログラム

メインプログラム
 ##	 表示したいビジネスデータ
 list	 =	 ['A',	 'B',	 'C']
 context	 =	 {	 :list	 =>	 list	 }

 ##	 テンプレートを読み込んで表示
 require	 'erubis'
 eruby	 =	 Erubis::Eruby.load_file('ex.rhtml')
 html	 =	 eruby.evaluate(context)
 print	 html
                                                       ふつうにeRubyファイ
                                                       ルとして実行するだけ

                   copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                           44
特長と欠点
✤   特長   ✤   pure HTML テンプレートである
         ✤   実行速度が高速
         ✤   eRuby, PHP, JSP 等もサポート
         ✤   HTML以外でも利用可能


✤   欠点   ✤   コンパイルが面倒(自動化は可能)
         ✤   実行時エラーで報告される行番号がコンパイ
             ル後のものであり、コンパイル前の行番号で
             はない(言語のサポートが必要)

                copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                        45
応用例(1)

 要素全体を繰り返す                                          内容だけを繰り返す
 #list	 {                                            #list	 {
 	 	 logic:	 {                                       	 	 logic:	 {
 	 	 	 	 for	 item	 in	 @list                        	 	 	 	 _stag
 	 	 	 	 	 	 _stag	 #	 開始タグ                          	 	 	 	 for	 item	 in	 @list
 	 	 	 	 	 	 _cont	 #	 内容                            	 	 	 	 	 	 _cont
 	 	 	 	 	 	 _etag	 #	 終了タグ                          	 	 	 	 end
 	 	 	 	 end                                         	 	 	 	 _etag
 	 	 }                                               	 	 }
 }                                                   }             <dt>と<dd>を繰り
                                                                             返したいときに有用



                     copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                         46
応用例(2)

 条件を満たすときだけ出力                                       デフォルト値を出力
 #list	 {                                            #list	 {
 	 	 logic:	 {                                       	 	 logic:	 {
 	 	 	 	 if	 @list.size	 >	 0                        	 	 	 	 _stag
 	 	 	 	 	 	 _stag                                   	 	 	 	 if	 @name.blank?
 	 	 	 	 	 	 _cont                                   	 	 	 	 	 	 print('World')
 	 	 	 	 	 	 _etag                                   	 	 	 	 else
 	 	 	 	 end                                         	 	 	 	 	 	 _cont
 	 	 }                                               	 	 	 	 end
 }                                                   	 	 	 	 _etag
                                                     	 	 }
                                                     }

                     copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                  47
応用例(3)

 ダミータグを削除                                       ダミー要素を削除
 #list	 {                                       #list	 {
 	 	 logic:	 {                                  	 	 logic:	 {
 	 	 	 	 #_stag                                 	 	 }
 	 	 	 	 _cont                                  }
 	 	 	 	 #_etag
 	 	 }                                           他の要素で置換
 }
                                                   #list	 {
                                                   	 	 logic:	 {
                                                   	 	 	 	 _element(list2)
                                                   	 	 }
                                                   }              同じ要素を
                                                                          再利用できる
                  copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                   48
応用例(4)

 より複雑なプレゼンテーションロジック
 #list	 {
 	 	 attrs:	 "class"	 cls;	 	 #	 属性値を出力
 	 	 logic:	 {
 	 	 	 	 odd	 =	 false               プレゼンテーションロジックが
 	 	 	 	 for	 x	 in	 @list           HTMLから分離されている
 	 	 	 	 	 	 odd	 =	 !odd
 	 	 	 	 	 	 cls	 =	 odd	 ?	 'odd'	 :	 'even'
 	 	 	 	 	 	 _elem
 	 	 	 	 end                     プレゼンテーションロジックを変更
 	 	 }
                                 してもHTMLは変更する必要がない
 }

               copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                       49
ここまでのまとめ
✤   Kwartzテンプレートエンジン
    ✤   プレゼンテーションロジックをプレゼンテーション
        データ(=HTML)から分離


    ✤   pure HTML テンプレートを実現
    ✤   プレゼンテーションロジックを変更してもHTMLを変
        更する必要がない




                 copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                         50
Kwartz編:
プレゼンテーションパターン




           copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                   51
概要
✤   プレゼンテーションパターンとは?
    ✤   プレゼンテーション層に関するデザインパターン、ベス
        トプラクティス
    ✤   (オレオレ造語であり、一般的ではないことに注意)
    ✤   全然難しくないよ!
    ✤   http://www.kuwata-lab.com/kwartz/kwartz3ruby-
        pattern-catalog.html




                     copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                             52
パターン一覧
✤   Replacement                                      ✤    Iteration
    ✤   Replace Element with                               ✤    Iterate Element Pattern
        Value Pattern                                      ✤
                                                                Iterate Content Pattern
    ✤   Replace Content with
        Value Pattern                                ✤    Selection
    ✤   Default Content Pattern                            ✤    Select Element/Content
    ✤   Replace Element with                                    Pattern
        Element/Content Pattern                            ✤    Pick-up Element/Content
    ✤   Replace Content with                                    Pattern
        Element/Content Pattern                            ✤    Extract Element/Content
                                                                Pattern
✤   Deletion
    ✤   Delete Element Pattern                                                  今回はこちらを紹介
    ✤   Delete Tag Pattern
                        copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                            53
Select Element パターン
✤   要求: 表示するデータを条件によって変えたい

    <div	 id="mark:message">                     #message	 {
    	 	 <div	 id="error">                        	 	 logic:	 {
    	 	 	 	 ERROR!                               	 	 	 	 if	 status	 ==	 'error'
    	 	 </div>                                   	 	 	 	 	 	 _element(error)
    	 	 <div	 id="warning">                      	 	 	 	 elsif	 status	 ==	 'warn'
    	 	 	 	 Warning:                             	 	 	 	 	 	 _element(warning)
    	 	 </div>                                   	 	 	 	 else
    	 	 <div	 id="noerror">                      	 	 	 	 	 	 _element(noerror)
    	 	 	 	 No	 error.                           	 	 	 	 end
    	 	 </dvi>                                   	 	 }           条件によって該当
                     要素ごとに
    </div>                                       }               する要素を選択
                別のidを付加
                     copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                     54
Pick-up Element パターン
✤   要求: たくさんのダミー要素を含めたい(デザイン確認のため)

    <ol	 id="mark:list">                          #list	 {
    	 	 <li	 id="mark:item">                      	 	 logic:	 {
    	 	 	 	 Item1                                 	 	 	 	 _stag
    	 	 </li>      ダミーでない                         	 	 	 	 _element(item)
    	 	 <li>Item2</li>
                   要素にid属性                        	 	 	 	 _etag
    	 	 <li>Item3</li>
                   をつけるだけ                         	 	 }
    	 	 <li>Item4</li>                            }
    	 	 <li>Item5</li>                                          ダミーでない要素だけを
    	 	 <li>Item6</li>                                          取り出せば、ダミー要素
    </ol>                                                       はすべて削除される



                      copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                              55
Extract Element パターン
✤   要求: 文書全体からある特定の要素だけを取り出したい

    <html	 id="mark:whole">                     #whole	 {
    	 <body>                                    	 	 logic:	 {
    	 	 <form	 id="form">                       	 	 	 	 _element(form)
    	 	 	 <input	 ...	 />                       	 	 }
                                                              全体を特定の要素
    	 	 	 <input	 ...	 />                       }
                                                                            だけで置き換える
    	 	 	 <input	 ...	 />
    	 	 </form>                                 #DOCUMENT	 {
    	 </body> いちばん外側の                           	 	 logic:	 {
    </html>       要素である                         	 	 	 	 _element(form)
              <html>タグに
                                                	 	 }
                                                }         Kwartzではそのため
              id属性をつける                                          の特別なid名を提供
                    copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                                       56
ここまでのまとめ
✤   プレゼンテーションパターン
    ✤   プレゼンテーション層におけるベストプラクティス
    ✤   Select Element パターン:
          条件によって使う要素を変える
    ✤   Pick-up Element パターン:
           必要な要素だけを使い、残りはダミーとして捨てる
    ✤   Extract Element パターン:
          全体からある特定の要素だけを取り出す



                 copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                         57
まとめ




      copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                              58
まとめ
✤   pure HTMLテンプレートが理想
✤   そのためにはプレゼンテーションロジック
    だけを分離・独立させることが重要
✤   Kwartzはそれを実現してるよ!




           copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                   59
謝辞
✤   RubyKaigi事務局の皆様
✤   マイナー番組ご視聴の皆様


      ありがとうございました




            copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                                    60
questions?

  copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                          61
thank you

  copyright(c) 2010 kuwata-lab.com all rights reserved.
                                                          62

More Related Content

HTMLデザインを崩さないテンプレートエンジンの作り方

  • 1. RubyKaigi 2010 HTMLデザインを崩さない テンプレートエンジンの作り方 makoto kuwata http://www.kuwata-lab.com/ English ver: http://slidesha.re/a3s2ZZ copyright(c) 2010 kuwata-lab.com all rights reserved. 1
  • 2. はじめに 目的 ✤ テンプレートエンジン利用者に、正しい 知識を理解してもらう ✤ テンプレートエンジン設計者に、あるべ き姿を考えてもらう 動機 ✤ 間違った説明が蔓延しており是正したい ✤ eRubyは決して理想解ではないことを 知ってほしい 対象者 ✤ テンプレートエンジンの利用者と設計者 copyright(c) 2010 kuwata-lab.com all rights reserved. 2
  • 3. お詫び ✤ 今日話したかったこと ✤ テンプレートのデザインを崩さない方法について ✤ テンプレートエンジンの高速化について ✤ 既存のテンプレートエンジンが抱える問題点について ✤ デザインを崩さず、高速で、どの言語でも比較的簡単に 実装できるテンプレートエンジンの作り方について ✤ 30分しかないので最初の項目だけ ✤ 野心的すぎました、ごめんなさい copyright(c) 2010 kuwata-lab.com all rights reserved. 3
  • 4. 参考文献 ✤ Rubyist Magazine - テンプレートシステム入門 ✤ http://jp.rubyist.net/magazine/?0024-TemplateSystem ✤ http://jp.rubyist.net/magazine/?0024-TemplateSystem2 copyright(c) 2010 kuwata-lab.com all rights reserved. 4
  • 5. アジェンダ ✤ 基礎知識編 ✤ ビジネス層とプレゼンテーション層 ✤ 現状の問題点とその原因 ✤ プレゼンテーションロジック ✤ Kwartz編 ✤ はじめてのKwartz入門 ✤ プレゼンテーションパターン copyright(c) 2010 kuwata-lab.com all rights reserved. 5
  • 6. 基礎知識編: ビジネス層とプレゼンテーション層 copyright(c) 2010 kuwata-lab.com all rights reserved. 6
  • 7. ビジネス層とプレゼンテーション層 ✤ ビジネス層 ✤ 役割:「何を(what)表示するか?」を決定 ✤ 担当:メインプログラム ✤ プレゼンテーション層 ✤ 役割:「どのように(how)表示するか?」を決定 ✤ 担当:テンプレートファイルおよびエンジン copyright(c) 2010 kuwata-lab.com all rights reserved. 7
  • 8. データとロジック ✤ ビジネス層とプレゼンテーション層の両方に、 データとロジックが存在 ビジネス層 プレゼンテーション層 (メインプログラム) (テンプレートエンジン) プレゼンテーション データ ビジネスデータ データ プレゼンテーション ロジック ビジネスロジック ロジック テンプレートエンジンはここを分離 copyright(c) 2010 kuwata-lab.com all rights reserved. 8
  • 9. 具体例 ビジネスデータ ✤ 営業部員の売上成績から ビジネスロジック ✤ 上位 20 名を選出し、 ✤ 奇数行と偶数行で背景色を変えて プレゼンテー ✤ <table> タグで表示する ションロジック プレゼンテー ションデータ copyright(c) 2010 kuwata-lab.com all rights reserved. 9
  • 10. よくある間違い(1) (誤) ✤ テンプレートエンジンは、ロジックと プレゼンテーションを分離する ✤ テンプレートエンジンは、ビジネス層 (正) とプレゼンテーション層を分離する ✤ プレゼンテーション層にもロジックがある 自分も昔は間違ってました… copyright(c) 2010 kuwata-lab.com all rights reserved. 10
  • 11. よくある間違い(2) (誤) ✤ プレゼンテーション層にはロジックを 含めるべきではない ✤ プレゼンテーション層はプレゼンテー (正) ションロジックを含む ✤ 「HTMLテンプレートにプレゼンテーション ロジックを含めない」ことと、「ビジネス層 とプレゼンテーション層を分離する」こと は、別の話 copyright(c) 2010 kuwata-lab.com all rights reserved. 11
  • 12. ここまでのまとめ ✤ ビジネス層 ✤ 何を(What)表示するか? ✤ メインプログラムが担当 ✤ プレゼンテーション層 ✤ どう(How)表示するか? ✤ テンプレートファイルが担当 ✤ どちらにもデータとロジックが存在 copyright(c) 2010 kuwata-lab.com all rights reserved. 12
  • 13. 基礎知識編: 現状の問題点とその原因 copyright(c) 2010 kuwata-lab.com all rights reserved. 13
  • 14. デザイナ泣かせの現状 ProjectA: Rails <table> ProjectC: PHP <% @arr.each { %> <table> .... <?php foreach() { ?> <% } %> .... </table> <?php } ?> </table> ProjectB: JSP <table> <forEach items=""> プログラマの都合を .... デザイナに押し付け </forEach> ているのが現状 </table> copyright(c) 2010 kuwata-lab.com all rights reserved. 14
  • 15. 共同作業での問題 テンプレートファイル <table> <% @arr.each { %> .... <% } %> </table> 衝突! プレゼンテーション HTMLを編集 ロジックを編集 デザイナ プログラマ copyright(c) 2010 kuwata-lab.com all rights reserved. 15
  • 16. 問題の原因 ✤ テンプレート中にプレ テンプレートファイル ゼンテーションロジッ <table> クを埋め込んでいるこ <% i = 0 %> <% @arr.eachx do |x| %> とこそが、諸悪の根源 <% i += i %> <% c = i.odd ? %> <% 'odd':'even' %> pure HTML テンプ <tr class="<%=c%>"> レートが望ましい <td><%= x %></td> </tr> <% end %> </table> copyright(c) 2010 kuwata-lab.com all rights reserved. 16
  • 17. pure HTML テンプレートの利点 ✤ HTMLデザインが崩れない(表示確認できる) デザイナ for ✤ テンプレート言語を学習しなくてよい ✤ HTML Validator でチェックできる ✤ 好きなエディタ (Dreamweaverなど) が使える 同時編集による衝突を避けやすい プログラマ for ✤ ✤ 空白除去による圧縮(転送量削減)がしやすい ✤ ケータイ用などに自動変換しやすい copyright(c) 2010 kuwata-lab.com all rights reserved. 17
  • 18. Matzも悩んだ問題 ✤ じゃあプレゼンテーションロジックは どこに書けばいいの? Matz日記 (2004-08-24) http://www.rubyist.net/ matz/20040824.html#p01 (要約) ViewそのものにLogicが必要な場合、 HTMLテンプレートでは記述できないし、 どこに所属すべきだろうか? copyright(c) 2010 kuwata-lab.com all rights reserved. 18
  • 19. ここまでのまとめ ✤ テンプレート中にプレゼンテーションロ ジックを埋め込むと、問題が多い ✤ pure HTMLテンプレートが望ましい ✤ プレゼンテーションロジックはどこに? copyright(c) 2010 kuwata-lab.com all rights reserved. 19
  • 20. 基礎知識編: プレゼンテーションロジック copyright(c) 2010 kuwata-lab.com all rights reserved. 20
  • 21. プレゼンテーションロジックをどこに? A. テンプレートファイル中 (eRuby, JSP, Kid) プレゼンテーションロジック ビジネスロジック&データ +プレゼンテーションデータ B. メインプログラム中 (Amrita2, XMLC, HTML::Template) プレゼンテーションロジック プレゼンテーションデータ +ビジネスロジック&データ C. 独立した別ファイル中 (Kwartz, Tapestry, Mayaa) プレゼンテーションロジック ビジネスロジック&データ プレゼンテーションデータ テンプレート メインプログラム copyright(c) 2010 kuwata-lab.com all rights reserved. 21
  • 22. A. テンプレートファイル中に記述 (1) 例: eRuby ファイル (Ruby) <table> <% odd = false %> <% for item in @list %> <% odd = ! odd <% cls = odd ? 'odd' : 'even' %> <tr class="<%= cls %>"> <td><%=h item %></td> </tr> •HTMLの中にHTML <% end %> でないものが混在 </table> →pure HTML でない copyright(c) 2010 kuwata-lab.com all rights reserved. 22
  • 23. A. テンプレートファイル中に記述 (2) 例: JSP ファイル (Java) <table> <c:forEach var="item" items="${list}" varStatus="loop"> <c:set var="klass" value="${loop.count%2==0?'odd':'even'}" /> <tr class="${klass}"> <td><c:out value="${item}" /></td> </tr> </c:forEach> •カスタムタグを使おうが、ロジックを </table> テンプレートファイル中に埋め込んで いるという点ではeRubyと同じ copyright(c) 2010 kuwata-lab.com all rights reserved. 23
  • 24. A. テンプレートファイル中に記述 (3) 例: Kid テンプレートファイル (Python) <table> <tr py:for="i, item in enumerate(items)" class="${i % 2 and 'even' or 'odd'}"> <td py:content="item">dummy</td> </tr> </table> •文書構造と属性を使うことで、 HTMLデザインを崩さないよう配慮 •ロジックをテンプレートファイル中に 埋め込んでいるという点では同じ copyright(c) 2010 kuwata-lab.com all rights reserved. 24
  • 25. A. テンプレートファイル中に記述 (4) プレゼンテーション層(=テンプレート)が 利 ✤ ビジネス層から分離されている 点 ✤ 使い方がわかりやすく、実装も簡単 pure HTML でない(ことが多い) 欠 ✤ ✤ 同時編集による衝突が発生しやすい 点 ✤ デザイナがプレゼンテーションロジックを 誤って変更する可能性がある copyright(c) 2010 kuwata-lab.com all rights reserved. 25
  • 26. プレゼンテーションロジックをどこに? A. テンプレートファイル中 (eRuby, JSP, Kid) プレゼンテーションロジック ビジネスロジック&データ +プレゼンテーションデータ B. メインプログラム中 (Amrita2, XMLC, HTML::Template) プレゼンテーションロジック プレゼンテーションデータ +ビジネスロジック&データ C. 独立した別ファイル中 (Kwartz, Tapestry, Mayaa) プレゼンテーションロジック ビジネスロジック&データ プレゼンテーションデータ テンプレート メインプログラム copyright(c) 2010 kuwata-lab.com all rights reserved. 26
  • 27. B. メインプログラム中に記述 (1) 例: Amrita2 テンプレートファイル (Ruby) <table> <tr id="list" class="odd"> <td id="item">dummy</td> </tr> </table> •書き換えたい場所に「目印」を書くだけ (Amrita2ならid属性をつけるだけ) •テンプレートが pure HTML (ロジック を埋め込まないため) copyright(c) 2010 kuwata-lab.com all rights reserved. 27
  • 28. B. メインプログラム中に記述 (2) 例: Amrita2 メインプログラム (Ruby) ## 表示したいビジネスデータ list = [ 'A', 'B', 'C' ] •ビジネスデータをプレゼ ## プレゼンテーションロジック ンテーションロジックで list2 = []; odd = false 加工する必要がある for x in list cls = (odd = !odd) ? 'odd' : 'even' item2 = a(:class=>cls) { {:item=>x} } list2 << item2 end context = { :list=>list2 } ## テンプレートを読み込んで表示 tmpl = Amrita2::TemplateFile.new('ex1.html') tmpl.expand(html='', context) print html copyright(c) 2010 kuwata-lab.com all rights reserved. 28
  • 29. B. メインプログラム中に記述 (3) テンプレートには目印を埋め込むだけ 利 ✤ pure HTML テンプレートを実現 (しやすい) 点 ✤ ✤ 同じファイルを編集しないので衝突しない ✤ デザイナによるロジックの誤変更がない ビジネス層とプレゼンテーション層が分離で 欠 ✤ きてない(*注) 点 ✤ 使い方にクセがある(ロジックをデータで表 現する必要があるため) (*注) 工夫次第で回避可能(該当箇所を別クラスにする等) copyright(c) 2010 kuwata-lab.com all rights reserved. 29
  • 30. プレゼンテーションロジックをどこに? A. テンプレートファイル中 (eRuby, JSP, Kid) プレゼンテーションロジック ビジネスロジック&データ +プレゼンテーションデータ B. メインプログラム中 (Amrita2, XMLC, HTML::Template) プレゼンテーションロジック プレゼンテーションデータ +ビジネスロジック&データ C. 独立した別ファイル中 (Kwartz, Tapestry, Mayaa) プレゼンテーションロジック ビジネスロジック&データ プレゼンテーションデータ テンプレート メインプログラム copyright(c) 2010 kuwata-lab.com all rights reserved. 30
  • 31. C. 独立した別ファイル中に記述 (1) 例: Kwartz プレゼンテーションデータファイル (Ruby) <table> <tr id="mark:list" class="odd"> <td id="mark:item">dummy</td> </tr> </table> •書き換えたい場所に「目印」を書くだけ (Kwartzならid属性をつけるだけ) copyright(c) 2010 kuwata-lab.com all rights reserved. 31
  • 32. C. 独立した別ファイル中に記述 (2) 例: Kwartz プレゼンテーションロジックファイル (Ruby) #item { ## id="mark:item" は value: x; ## x の値を表示する } #list { ## id="mark:list" は logic: { ## 要素全体をループする for x in @list _elem end } •あたかもCSSのようにプレゼンテー } ションロジックを記述する •プレゼンテーションロジックがメイ ンプログラム中に現れない! copyright(c) 2010 kuwata-lab.com all rights reserved. 32
  • 33. CSS (Visual Design) HTML (Document Structure) Kwartz JavaScript (Presentation (Client-side Logic) Logic) copyright(c) 2010 kuwata-lab.com all rights reserved. 33
  • 34. C. 独立した別ファイル中に記述 (3) ✤ ビジネス層とプレゼンテーション層がきれい 利 に分離 点 ✤ プレゼンテーションデータ(HTML)とプレ ゼンテーションロジックもきれいに分離 ✤ pure HTML テンプレートを実現 ✤ 編集するファイルが別なので衝突しない ✤ デザイナによるロジックの誤変更がない 欠 ✤ ファイル数が増える 点 copyright(c) 2010 kuwata-lab.com all rights reserved. 34
  • 35. 大事なことと本当に大事なこと ✤ 大事なこと ✤ テンプレートが pure HTML であること ✤ 本当に大事なこと ✤ プレゼンテーションロジックを分離・独立させること ✤ (pure HTML はその副産物にすぎない) copyright(c) 2010 kuwata-lab.com all rights reserved. 35
  • 36. よくある間違い(1) (誤) ✤ テンプレートがpure HTMLなので、 プレゼンテーション層を分離できてい ます! ✤ pure HTMLであることと、各層が分 (正) 離できることは、別個のお話 ✤ 恐らく、HTMLファイル中にロジックが現れ ないことを「プレゼンテーション層の分離」 と勘違いしている copyright(c) 2010 kuwata-lab.com all rights reserved. 36
  • 37. よくある間違い(2) (誤) ✤ 生PHPだとデザイナが変なロジックを 埋め込む可能性があるので、Smarty を導入しました! ✤ Smartyではデザイナによる誤変更は防 (正) 止できない ✤ デザイナがプレゼンテーションロジックにア クセスできる時点で間違い ✤ 根本的な解決法は、プレゼンテーションロ ジックを分離すること copyright(c) 2010 kuwata-lab.com all rights reserved. 37
  • 38. ここまでのまとめ ✤ プレゼンテーションロジックの記述場所 ✤ テンプレートファイル中(デザイン崩れ、競合が発生) ✤ メインプログラム中(分離がいまいち) ✤ 独立した別ファイル中(いちばん理想的) ✤ pure HTML テンプレートは重要 ✤ プレゼンテーションロジックの分離・独立 はもっと重要 copyright(c) 2010 kuwata-lab.com all rights reserved. 38
  • 39. Kwartz編: はじめてのKwartz入門 copyright(c) 2010 kuwata-lab.com all rights reserved. 39
  • 40. Kwartz 概要 ✤ Kwartzとは? ✤ プレゼンテーションデータ(HTML)と プレゼンテーションロジックを分離できるテンプレー トエンジン ✤ pure HTML テンプレート ✤ Ruby実装とPHP実装を用意 ✤ http://www.kuwata-lab.com/kwartz/ copyright(c) 2010 kuwata-lab.com all rights reserved. 40
  • 41. サンプル: プレゼンテーションデータ 書き換えたい箇所に、目印 ex.html となるid属性をつける <table> <tr id="mark:list"> <td id="mark:item">Foo</td> </tr> <tr id="dummy:d1"> <td>Bar</td> </tr> </table> 「id="dummy:xxx"」は ダミー要素を表す copyright(c) 2010 kuwata-lab.com all rights reserved. 41
  • 42. サンプル: プレゼンテーションロジック ex.plogic id属性ごとにプレゼンテー #list { ションロジックを記述 logic: { for x in @list _stag ## 開始タグ _cont ## 内容 _etag ## 終了タグ end } <tr>要素を繰り返し } #item { value: x; } <td>要素に値を出力 copyright(c) 2010 kuwata-lab.com all rights reserved. 42
  • 43. サンプル: コンパイル eRubyファイルへコンパイル $ kwartz -l eruby -p ex.plogic ex.html > ex.rhtml ex.rhtml (コンパイル結果) <table> <% for x in @list %> <tr> <td><%= x %></td> •属性「id="mark:xxx"」は </tr> コンパイル時に削除される <% end %> (id="xxx" なら削除されない) </table> •「id="dummy:xxx"」は要素 そのものが削除される copyright(c) 2010 kuwata-lab.com all rights reserved. 43
  • 44. サンプル: メインプログラム メインプログラム ## 表示したいビジネスデータ list = ['A', 'B', 'C'] context = { :list => list } ## テンプレートを読み込んで表示 require 'erubis' eruby = Erubis::Eruby.load_file('ex.rhtml') html = eruby.evaluate(context) print html ふつうにeRubyファイ ルとして実行するだけ copyright(c) 2010 kuwata-lab.com all rights reserved. 44
  • 45. 特長と欠点 ✤ 特長 ✤ pure HTML テンプレートである ✤ 実行速度が高速 ✤ eRuby, PHP, JSP 等もサポート ✤ HTML以外でも利用可能 ✤ 欠点 ✤ コンパイルが面倒(自動化は可能) ✤ 実行時エラーで報告される行番号がコンパイ ル後のものであり、コンパイル前の行番号で はない(言語のサポートが必要) copyright(c) 2010 kuwata-lab.com all rights reserved. 45
  • 46. 応用例(1) 要素全体を繰り返す 内容だけを繰り返す #list { #list { logic: { logic: { for item in @list _stag _stag # 開始タグ for item in @list _cont # 内容 _cont _etag # 終了タグ end end _etag } } } } <dt>と<dd>を繰り 返したいときに有用 copyright(c) 2010 kuwata-lab.com all rights reserved. 46
  • 47. 応用例(2) 条件を満たすときだけ出力 デフォルト値を出力 #list { #list { logic: { logic: { if @list.size > 0 _stag _stag if @name.blank? _cont print('World') _etag else end _cont } end } _etag } } copyright(c) 2010 kuwata-lab.com all rights reserved. 47
  • 48. 応用例(3) ダミータグを削除 ダミー要素を削除 #list { #list { logic: { logic: { #_stag } _cont } #_etag } 他の要素で置換 } #list { logic: { _element(list2) } } 同じ要素を 再利用できる copyright(c) 2010 kuwata-lab.com all rights reserved. 48
  • 49. 応用例(4) より複雑なプレゼンテーションロジック #list { attrs: "class" cls; # 属性値を出力 logic: { odd = false プレゼンテーションロジックが for x in @list HTMLから分離されている odd = !odd cls = odd ? 'odd' : 'even' _elem end プレゼンテーションロジックを変更 } してもHTMLは変更する必要がない } copyright(c) 2010 kuwata-lab.com all rights reserved. 49
  • 50. ここまでのまとめ ✤ Kwartzテンプレートエンジン ✤ プレゼンテーションロジックをプレゼンテーション データ(=HTML)から分離 ✤ pure HTML テンプレートを実現 ✤ プレゼンテーションロジックを変更してもHTMLを変 更する必要がない copyright(c) 2010 kuwata-lab.com all rights reserved. 50
  • 51. Kwartz編: プレゼンテーションパターン copyright(c) 2010 kuwata-lab.com all rights reserved. 51
  • 52. 概要 ✤ プレゼンテーションパターンとは? ✤ プレゼンテーション層に関するデザインパターン、ベス トプラクティス ✤ (オレオレ造語であり、一般的ではないことに注意) ✤ 全然難しくないよ! ✤ http://www.kuwata-lab.com/kwartz/kwartz3ruby- pattern-catalog.html copyright(c) 2010 kuwata-lab.com all rights reserved. 52
  • 53. パターン一覧 ✤ Replacement ✤ Iteration ✤ Replace Element with ✤ Iterate Element Pattern Value Pattern ✤ Iterate Content Pattern ✤ Replace Content with Value Pattern ✤ Selection ✤ Default Content Pattern ✤ Select Element/Content ✤ Replace Element with Pattern Element/Content Pattern ✤ Pick-up Element/Content ✤ Replace Content with Pattern Element/Content Pattern ✤ Extract Element/Content Pattern ✤ Deletion ✤ Delete Element Pattern 今回はこちらを紹介 ✤ Delete Tag Pattern copyright(c) 2010 kuwata-lab.com all rights reserved. 53
  • 54. Select Element パターン ✤ 要求: 表示するデータを条件によって変えたい <div id="mark:message"> #message { <div id="error"> logic: { ERROR! if status == 'error' </div> _element(error) <div id="warning"> elsif status == 'warn' Warning: _element(warning) </div> else <div id="noerror"> _element(noerror) No error. end </dvi> } 条件によって該当 要素ごとに </div> } する要素を選択 別のidを付加 copyright(c) 2010 kuwata-lab.com all rights reserved. 54
  • 55. Pick-up Element パターン ✤ 要求: たくさんのダミー要素を含めたい(デザイン確認のため) <ol id="mark:list"> #list { <li id="mark:item"> logic: { Item1 _stag </li> ダミーでない _element(item) <li>Item2</li> 要素にid属性 _etag <li>Item3</li> をつけるだけ } <li>Item4</li> } <li>Item5</li> ダミーでない要素だけを <li>Item6</li> 取り出せば、ダミー要素 </ol> はすべて削除される copyright(c) 2010 kuwata-lab.com all rights reserved. 55
  • 56. Extract Element パターン ✤ 要求: 文書全体からある特定の要素だけを取り出したい <html id="mark:whole"> #whole { <body> logic: { <form id="form"> _element(form) <input ... /> } 全体を特定の要素 <input ... /> } だけで置き換える <input ... /> </form> #DOCUMENT { </body> いちばん外側の logic: { </html> 要素である _element(form) <html>タグに } } Kwartzではそのため id属性をつける の特別なid名を提供 copyright(c) 2010 kuwata-lab.com all rights reserved. 56
  • 57. ここまでのまとめ ✤ プレゼンテーションパターン ✤ プレゼンテーション層におけるベストプラクティス ✤ Select Element パターン: 条件によって使う要素を変える ✤ Pick-up Element パターン: 必要な要素だけを使い、残りはダミーとして捨てる ✤ Extract Element パターン: 全体からある特定の要素だけを取り出す copyright(c) 2010 kuwata-lab.com all rights reserved. 57
  • 58. まとめ copyright(c) 2010 kuwata-lab.com all rights reserved. 58
  • 59. まとめ ✤ pure HTMLテンプレートが理想 ✤ そのためにはプレゼンテーションロジック だけを分離・独立させることが重要 ✤ Kwartzはそれを実現してるよ! copyright(c) 2010 kuwata-lab.com all rights reserved. 59
  • 60. 謝辞 ✤ RubyKaigi事務局の皆様 ✤ マイナー番組ご視聴の皆様 ありがとうございました copyright(c) 2010 kuwata-lab.com all rights reserved. 60
  • 61. questions? copyright(c) 2010 kuwata-lab.com all rights reserved. 61
  • 62. thank you copyright(c) 2010 kuwata-lab.com all rights reserved. 62