PAB@求職活動中

求職活動中とありますが、活動報告というよりは、技術の話題を多めでいきます。Scalaが大好きなので特にScalaの話が中心になると思います。

今回は\(^o^)/とテンションを上げるほどでもないのですが、まあ、シリーズなのでw

GaedsのGiter8テンプレートを作ろうと思って、そのためのサンプルアプリを作ったのですが、 そこで使ったテンプレートエンジンのTwirlが結構いいと思ったので紹介したいと思います。 Giter8テンプレートについては次回に詳しく説明するので、今回はサンプルアプリのほうに注目します。

ScalaのテンプレートエンジンというとScalateが有名なんですが、 Google App Engineにローカルファイルを作成できない制限なんかがあって、 Scalateをそのまま使うのは難しいんですね。 なので、今回はTwirlという別のテンプレートエンジンを使うことにしました。

前回までの記事

Twirl

spray/twirl

TwirlはPlay2.0のテンプレートエンジンを単独で使えるようにしたものです。 依存関係も完全に切り離されているので、他のPlay2.0の知識が必要ということもないです。

基本的にPlay2.0のドキュメントが参考になります。 Play2.0のドキュメントは日本語に翻訳してくださってる人たちがいるので、 そちら読むとわかりやすいです。

テンプレートエンジン · playframework-ja/Play20 Wiki

Twirl(というかPlay2.0のテンプレートエンジン)の特徴は、テンプレートがScalaの関数に変換されるということですね。 これにより、テンプレートを呼び出すのも簡単だし、テンプレート同士を組み合わせるのも簡単だし、 タイプセーフでもあるというScalaらしいライブラリだと思います。

サンプルアプリ

作ったのは簡単な一行掲示板です。

Message Board

Twitter Bootstrapを使って体裁は整えていますが、コードにすると40行程度の単純なコードです。 いかにもなサンプルアプリですね。

コードはこちらになります。

hexx/gaeds-sample

ディレクトリ構成

gaeds-sample
├── build.sbt
├── project
│   └── plugins.sbt
└── src
    └── main
        ├── scala
        │   └── board.scala
        ├── twirl
        │   ├── board.scala.html
        │   ├── form.scala.html
        │   ├── index.scala.html
        │   └── main.scala.html
        └── webapp
            ├── WEB-INF
            │   ├── appengine-web.xml
            │   └── web.xml
            ├── css
            │   ├── bootstrap-responsive.min.css
            │   └── bootstrap.min.css
            ├── img
            │   ├── glyphicons-halflings-white.png
            │   └── glyphicons-halflings.png
            └── js
                └── bootstrap.min.js

テンプレートはsrc/main/twirlの下に置きます。 cssimgjsに入ってるのはTwitter Bootstrapのファイルです。 あとは、前に説明したApp Engineの構成と同じですね。

コード

ほとんどいつもと同じコードなので、ポイントだけ。

case class Twirl(html: twirl.api.Html) extends ComposeResponse(HtmlContent ~> ResponseString(html.body))

UnfilteredでTwirlを使う場合はこのケースクラスを定義して使うようにすると便利です。 HTMLのレスポンスヘッダを付けて、HTMLを返すという処理です。

  def view = Ok ~> Twirl(html.index())

ここで使っているhtml.indexという関数ですが、Twirlがテンプレートから生成します。 src/main/twirl/index.scala.htmlというファイルがhtml.indexという関数になります。 この関数はコードやテンプレート中のどこからでも制限なく使えます。

それではテンプレートのほうを見てみましょう。

テンプレート

  • form.scala.html
  • board.scala.html
  • main.scala.html
  • index.scala.html

単純なアプリなので四つに分ける必要なんて全然ないんですけど、分けやすいのでこうしたくなるんですよね。

テンプレート内の詳しい文法は前述の日本語ドキュメントを参照してください。

テンプレートエンジン · playframework-ja/Play20 Wiki

シンプルなのですぐに覚えることができると思います。

form.scala.html

これは純粋なformのHTMLの部品ですね。他のテンプレートから使います。

board.scala.html

これは掲示板の表示部分です。上と同じく他のテンプレートから使います。 見たとおりテンプレート中のScalaのコードも自然に書けます。

一つ注意としては @for( の部分はスペースを開けずに書くということですね。 テンプレート内のScalaのコードとHTMLの区別はTwirlが自動的におこなってくれるのですが、 スペースを開けるとうまくいかないみたいです。

main.scala.html

これはガワの部分ですね。引数を取るテンプレートになってます。

index.scala.html

タイトルと部品を組み合わせて完全なページを作っています。 これがコード中で呼び出している関数に変換されるわけです。

Play2.0とGoogle App Engine

TwirlがPlay2.0のテンプレートエンジンということで、 だったらUnfilteredじゃなくてPlay2.0を使ったほうがいいんじゃね?と思われるかもしれませんが、 現時点のPlay framework 2.0.1ではwarパッケージを作ることができないので、 Google App Engineには使えないみたいです。

一応warを作ることができるプラグインもあるみたいなのですが、 まだ実用は難しいようです。

Twitter / takezoen: play2-war-pluginを試してみた。

dlecan/play2-war-plugin

Play2.1でwarパッケージに対応予定ということなので、そうなったら試してみたいと思います。

まとめ

今回はテンプレートエンジンのTwirlについて解説しました。 僕の感想としてはTwirlはシンプルでタイプセーフというScalaらしいライブラリだなと思いました。 まあ、Play2.0自体がそうできているんだと思いますが。 Google App Engineで使うならこれがいいんじゃないですかね。

いつの間にかGiter8テンプレートの一覧ができてた。n8han氏セレクトなのかな?

完成させてくれー

nomorescriptとは ScalaのコードをJavaScriptに変換するscalaのコンパイラープラグインです。