くんすとの備忘録

IT系技術メモ

移転しました。

15秒後に自動的にリダイレクトします。

【Play2.2】Scalaテンプレートファイル内に再利用可能なブロックを定義してみた

Play Framework 2.2 のScalaテンプレート(views/*.scala.html)内に、再利用可能ブロックを定義してみました。

まずはソース

app/views/index.scala.html

@(message: String)

@jslink(js: String) = {
	<script src="@js" type="text/javascript"></script>
}
@title = @{
	val head = "【テスト環境】"
	val appname = "hogehoge"
	head + appname 
}
<!DOCTYPE html>
<html>
    <head>
        <title>@title</title>
        <script src="@routes.Assets.at("javascripts/jquery-1.9.0.min.js")" type="text/javascript"></script>
        @jslink("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js")
        @jslink(routes.Assets.at("javascripts/jquery-1.9.0.min.js").url)
    </head>
    <body>
        Hello World!
    </body>
</html>

コンパイルされたScalaソース(target/scala-2.10/src_managed/main/views/html/index.template.scala)

package views.html

import play.templates._
import play.templates.TemplateMagic._

import play.api.templates._
import play.api.templates.PlayMagic._
import models._
import controllers._
import java.lang._
import java.util._
import scala.collection.JavaConversions._
import scala.collection.JavaConverters._
import play.api.i18n._
import play.core.j.PlayMagicForJava._
import play.mvc._
import play.data._
import play.api.data.Field
import play.mvc.Http.Context.Implicit._
import views.html._
/**/
object index extends BaseScalaTemplate[play.api.templates.HtmlFormat.Appendable,Format[play.api.templates.HtmlFormat.Appendable]](play.api.templates.HtmlFormat) with play.api.templates.Template1[String,play.api.templates.HtmlFormat.Appendable] {

    /**/
    def apply/*1.2*/(message: String):play.api.templates.HtmlFormat.Appendable = {
        _display_ {
def /*3.2*/jslink/*3.8*/(js: String):play.api.templates.HtmlFormat.Appendable = {_display_(

Seq[Any](format.raw/*3.24*/("""
	<script src=""""),_display_(Seq[Any](/*4.16*/js)),format.raw/*4.18*/("""" type="text/javascript"></script>
""")))};def /*6.2*/title/*6.7*/ = {{
	val head = "【テスト環境】"
	val appname = "hogehoge"
	head + appname 
}};
Seq[Any](format.raw/*1.19*/("""

"""),format.raw/*5.2*/("""
"""),format.raw/*10.2*/("""
<!DOCTYPE html>
<html>
    <head>
        <title>"""),_display_(Seq[Any](/*14.17*/title)),format.raw/*14.22*/("""</title>
        <script src=""""),_display_(Seq[Any](/*15.23*/routes/*15.29*/.Assets.at("javascripts/jquery-1.9.0.min.js"))),format.raw/*15.74*/("""" type="text/javascript"></script>
        """),_display_(Seq[Any](/*16.10*/jslink("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"))),format.raw/*16.83*/("""
        """),_display_(Seq[Any](/*17.10*/jslink(routes.Assets.at("javascripts/jquery-1.9.0.min.js").url))),format.raw/*17.73*/("""
    </head>
    <body>
        Hello World!
    </body>
</html>"""))}
    }
    
    def render(message:String): play.api.templates.HtmlFormat.Appendable = apply(message)
    
    def f:((String) => play.api.templates.HtmlFormat.Appendable) = (message) => apply(message)
    
    def ref: this.type = this

}
                /*
                    -- GENERATED --
                    DATE: Sat Dec 14 23:05:42 JST 2013
                    SOURCE: C:/usr/workspace/Java/playProject/app/views/index.scala.html
                    HASH: 12d570f04484050ca0b144e2def00f478fac70d9
                    MATRIX: 774->1|868->21|881->27|977->43|1028->59|1051->61|1109->99|1121->104|1223->18|1251->97|1279->176|1366->227|1393->232|1460->263|1475->269|1542->314|1622->358|1717->431|1763->441|1848->504
                    LINES: 26->1|28->3|28->3|30->3|31->4|31->4|32->6|32->6|37->1|39->5|40->10|44->14|44->14|45->15|45->15|45->15|46->16|46->16|47->17|47->17
                    -- GENERATED --
                */
            

出力されたHTML




<!DOCTYPE html>
<html>
    <head>
        <title>【テスト環境】hogehoge</title>
        <script src="/assets/javascripts/jquery-1.9.0.min.js" type="text/javascript"></script>
        
	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>

        
	<script src="/assets/javascripts/jquery-1.9.0.min.js" type="text/javascript"></script>

    </head>
    <body>
        Hello World!
    </body>
</html>

ざっくりとした解説

まず、Scalaテンプレートファイルの先頭で、2種類の再利用可能ブロックを定義しています。

@jslink(js: String) = {
	<script src="@js" type="text/javascript"></script>
}
@title = @{
	val head = "【テスト環境】"
	val appname = "hogehoge"
	head + appname 
}

1つ目の「jslink」は中括弧の先頭に「@」が無いため『再利用可能なコードブロック』で、2つ目の「title」は中括弧の先頭に「@」がある為『再利用可能な Scala のコードブロック』となっています。

『再利用可能なコードブロック』

内容はScalaテンプレートに変換されています。
コンパイルされたScalaソースを見ると、<!DOCTYPE html>以下と同じような処理をされているようです。

実際、

@jslink(js: String) = {
	<script src="@js" type="text/javascript"></script>
}
@jslink("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js")
@jslink(routes.Assets.at("javascripts/jquery-1.9.0.min.js").url)

これが

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="/assets/javascripts/jquery-1.9.0.min.js" type="text/javascript"></script>

こう変換されました。

『再利用可能な Scala のコードブロック』

内容はScalaコードそのものに変換されています。
コンパイルされたScalaソースを見ても、通常の関数定義に変換されているようです。

実際、

@title = @{
	val head = "【テスト環境】"
	val appname = "hogehoge"
	head + appname 
}
<title>@title</title>

これが

<title>【テスト環境】hogehoge</title>

こう変換されました。