Hatena::ブログ(Diary)

すにぺっと

2011-05-31

play-scalaを改めて学ぶ-16 Scala templates その2

| 17:54 | play-scalaを改めて学ぶ-16 Scala templates その2を含むブックマーク

では今回からScala templatesの具体的なところを。


Syntax: the magic ‘@’ character

Scalaテンプレートは'@'を特殊文字として使用する。

この文字が見つかるたび、Scala構文が始まることを示す。

便利なことに、明示的にコードブロックを閉じる必要はなく、うまく推測してくれるという。

いままでのスクリプトレットみたいにコードのはじまりと終わりをセットで意識しなくていいらしい。


Hello @customer.name!
         ^^^^^^^^^^^^^^
        Scala code

テンプレートエンジンは、自動的にコードを分析することによって、

コードブロックの終了を検出する。それだけでシンプルな文が書ける。

複数のトークンの文を書きたい場合、明示的に( )を使用する

Hello @(customer.firstName + customer.lastName)!
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
                    Scala Code

また、マルチステートメントのブロックを書き込むには、Scalaの{ }を使用可能。

Hello @{val name = customer.firstName + customer.lastName; name}!
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                             Scala Code

特別な意味の@はそのまま@を使用。
メアドとかで使う@として書きたい場合、@@と書いてエスケープする。

Template parameters

テンプレート関数なので、パラメータを必要とする。

テンプレートパラメータは、最初のテンプレートの行で宣言しなければならない。

@(customer:models.Customer, orders:Seq[models.Order])

デフォルト引数の指定も可能。

@(title:String = "Home")

いくつかのパラメータグループもとることができる。

@(title:String)(body: => Html)

暗黙パラメータもOK。

@(title:String)(body: => Html)(implicit session:play.mvc.Scope.Session)

すべてのパラメータタイプ名は完全修飾する必要がある。


Looping

Scalaのfor文を使用可能で、これは標準的な方法。

テンプレートコンパイラは、ブロックの前に、yieldキーワードを追加するので注意。

<ul>
@for(p <- products) {
    <li>@p.name ($@p.price)</li>
} 
</ul>

でもせっかくScalaならこう書くのが普通。

<ul>
@products.map { p =>
    <li>@p.name ($@p.price)</li>
} 
</ul>

If-Blocks

別に特別なことはない。

Scalaのif文とおなじ。

@if(items.isEmpty) {
    <h1>Nothing to display</h1>
} else {
    <h1>@items.size items!</h1>
}

Pattern matching

パターンマッチもテンプレートで使える。

@connected match {
    
    case Admin(name) => {
        <span class="admin">Connected as admin (@name)</span>
    }
    
    case User(name) => {
        <span>Connected as @name</span>
    }
    
}

Declaring reusable blocks

再利用可能なコードブロックもつくれる。

@display(product:models.Product) = {
    @product.name ($@product.price)
}
 
<ul>
@products.map { p =>
    @display(product = p)
} 
</ul>

再利用可能なScalaのブロックを宣言することに注意。

@title(text:String) = @{
    text.split(' ').map(_.capitalize).mkString(" ")
}
 
<h1>@title("hello world")</h1>

Import statements

テンプレートの先頭(またはサブテンプレート)で自由にインポート可能。

@(customer:models.Customer, orders:Seq[models.Order])
 
@import utils._
 
…

Composing templates (tags, layouts, includes, etc.)

シンプルな関数テンプレートを使用すると、好きなやり方でそれらを構成できる。

以下は、一般的ないくつかの例。

・Layout

views/main.scala.htmlテンプレート をメインレイアウトとして定義。

@(title:String)(content: => Html)
 
<h1>@title</h1>
 
<hr>
 
<div id="main">
    @content
</div>
 
<hr>
 
<div id="footer">
    ...
</div>

見ての通り、このテンプレートには、2つのパラメータ(タイトルとHTMLブロック)を取る。

そして、別のビューである views/Application/index.scala.htmlテンプレートから、それを使用可能。

@main(title = "Home") {
    
    <h1>Home page</h1>
    
}

・Tags

HTMLタグを表示するviews/tags/notice.scala.htmlをかいてみよう。

@(level:String = "error")(body: (String) => Html)
 
@level match {
    
    case "success" => {
        <p class="success">
            @body("green")
        </p>
    }
    
    case "warning" => {
        <p class="warning">
            @body("orange")
        </p>
    }
    
    case "error" => {
        <p class="error">
            @body("red")
        </p>
    }
    
}

そして他のテンプレートから使う。

@import views.tags.html._
 
@notice("error") { color =>
    Oops, something is <span style="color:@color">wrong</span>
}

・Includes

特別なことはせず、テンプレートを呼び出すことができる。

<h1>Home</h1>
 
<div id="side">
    @views.common.html.sideBar()
</div>


どんどん便利になっていくplayframeworkとplay-scala.


プログラミングScala
プログラミングScala
posted with amazlet at 11.05.31
Dean Wampler Alex Payne
オライリージャパン
売り上げランキング: 48964

トラックバック - http://d.hatena.ne.jp/sy-2010/20110531/1306832074
リンク元
Connection: close