Gradle で Hello Scalate on Scalatra

f:id:Naotsugu:20150603204450p:plain

blog1.mammb.com からの続きで、簡単な Hello Scalate をしてみます。

Scalate とは

Scala で書かれたテンプレートエンジンで、以下のシンタックスがサポートされています。

  • Mustache: 多くの言語で実装があり どこでも使えるテンプレートエンジン
  • Jade: 軽量マークアップ言語
  • Scaml: タグを % とインデントで書く Haml 形式のテンプレートエンジン
  • Ssp: JSPに似た Erb と Velocity 形式の記法が使えるテンプレートエンジン

Scala template で Scalate。

Scalatra から簡単に統合できます。ここでは SSP を例に見ていきます。

導入

前回までの例では scalatra は org.scalatra:scalatra_2.11 を指定していましたが、今回は scalate 統合用に scalatra-scalate_2.11 を利用します。

以下の依存に変更します。

compile 'org.scalatra:scalatra-scalate_2.11:2.4.0.RC1'

build.gradle は以下のようになります。

apply plugin: 'scala'
apply plugin:'application'

repositories {
    jcenter()
}

dependencies {
    compile 'org.scala-lang:scala-library:2.11.6'
    compile 'org.scala-lang:scala-xml:2.11.0-M4'

    compile 'org.scalatra:scalatra-scalate_2.11:2.4.0.RC1'
    compile 'org.eclipse.jetty:jetty-webapp:9.3.0.RC1'

    testCompile 'junit:junit:4.12'
    testCompile 'org.scalatest:scalatest_2.11:2.2.4'
    testRuntime 'org.scala-lang.modules:scala-xml_2.11:1.0.3'
}

mainClassName = 'JettyLauncher'

SSPページの作成

ScalatraServlet で Scalate を使うために ScalateSupport トレイトが提供されています。 SSP の利用は以下のように書くことができます。

import org.scalatra.ScalatraServlet
import org.scalatra.scalate.ScalateSupport

class HelloServlet extends ScalatraServlet with ScalateSupport {
  get("/") {
    ssp("/index")
  }
}

実際のテンプレートファイルはデフォルトで WEB-INF/templates/views を指します。

index.ssp ファイルを作成しましょう。

mkdir -p src/main/webapp/WEB-INF/templates/views 
touch src/main/webapp/WEB-INF/templates/views/index.ssp

index.ssp の中身は簡単のため以下の1行テキストにしてみます。

Hello Scalate!!

実行すると以下のようになります。

f:id:Naotsugu:20150601224300p:plain

ssp ファイルが利用されていますね。

Scala Server Page

先ほどの例では指定していませんでしたが、通常は contentType を以下のように指定します。

  get("/") {
    contentType="text/html"
    ssp("/index")
  }

index.ssp を以下のように変更してみましょう。

<%
 var foo = "hello"
 foo += " there"
 foo += " you!"
%>
<p>${foo}</p>

実行すると以下のようになります。

f:id:Naotsugu:20150601224625p:plain

テンプレートに記載した Scala コードが実行されて、結果がレンダリングされているのが確認できます。

パラメータを渡す

SSP にパラメータを渡すには以下のようにします。

  get("/") {
    contentType="text/html"
    ssp("/index", "foo" -> "uno", "bar" -> "dos")
  }

受け取り側のテンプレートでは <%@ %> でパラメータを受け取ります。

<%@ val foo: String %>
<%@ val bar: String %>
<p>Foo is <%= foo %></p>
<p>Bar is <%= bar %></p>

結果は以下のようにレンダリングされます。

f:id:Naotsugu:20150601225126p:plain

レイアウト

統一的なレイアウトと中身のコンテンツを分けて定義することができます。

レイアウトファイルは以下の階層がデフォルトで利用されます。

mkdir -p src/main/webapp/WEB-INF/layouts
touch src/main/webapp/WEB-INF/layouts/default.ssp

default.ssp の中身を以下のように書きます。

<%@ val body: String %>
<html>
    <head>
    <title>Scalate</title>
    </head>
    <body>
        <%= unescape(body) %>
    </body>
</html>

コンテンツの中身は<%= unescape(body) %>で指定した箇所に適用されます。そのままだとエスケープされてしまうため unescape() 指定が必要です。

実行すると以下のようになります。

f:id:Naotsugu:20150601232020p:plain

タイトルが反映されており、レイアウトとコンテンツが統合されていることが分かります。

SSP の文法

SSP(Scala Server Page)の文法を簡単に。Scalate のページまんまです。

<%= %> を使います。式は評価されて結果がレンダリングされます。

<p>
  <%= List("hi", "there", "reader!").mkString(" ") %>
</p>

以下のようにレンダリングされます。

<p>
  hi there reader!
</p>

Scala コード

<% %>を使います。コードが実行されますが、中身はレンダリング対象にはなりません。

<%
  var foo = "hello"
  foo += " there"
  foo += " you!"
%>
<p>${foo}</p>

以下のようにレンダリングされます。

<p>hello there you!</p>

Velocity スタイル で ${ } のようにも書けます。

属性

<%@ %> を使います。外部から受け取るパラメータを定義します。

<%@ val foo: MyType %>

デフォルト値を以下のように指定することができます。

<%@ val bar: String = "this is the default value" %>

Velocity スタイル で #{ }# のようにも書けます。

Forループ

Velocity スタイル で 以下のように書きます。

<ul>
#for (i <- 1 to 5)
  <li>${i}</li>
#end
</ul>

If Else

Velocity スタイル で 以下のように書きます。

<p>
#if (n == "James")
  Hey James
#elseif (n == "Hiram")
  Yo Hiram
#else
  Dunno
#end
</p>

あとはこちらを参照してください。。