S-JIS[2012-03-11] 変更履歴
Play framework 2.0の雛形の処理の流れを追ってみたメモ。
Play2.0の雛形アプリケーションを実行した際に処理(クラス・テンプレート)が呼ばれる順序。
http://localhost:9000
」にアクセスする。conf/routes
の設定を参照する。# Home page
GET / controllers.Application.index
app/conrollers/Application.scala
)のindexメソッド(コントローラー)が呼ばれる。package controllers
object Application extends Controller { def index = Action { Ok(views.html.index("Your new Application is ready.")) } }
app/views/index.scala.html
から生成される。@(message: String) @main("Welcome to Play 2.0") { @play20.welcome(message) }
app/views/main.scala.html
から生成される。@(title: String)(content: Html) <!DOCTYPE html> <html> <head> <title>@title</title> <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")"> <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")"> <script src="@routes.Assets.at("javascripts/jquery-1.7.1.min.js")" type="text/javascript"></script> </head> <body> @content </body> </html>
routes(ルート定義ファイル)には、HTTPでアクセスされたときのメソッド(GETとか)とパスと処理内容(どのオブジェクト を呼ぶか)を指定する。
# Routes # This file defines all application routes (Higher priority routes first) # ~~~~ # Home page GET / controllers.Application.index # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.at(path="/public", file)
assetsは、別言語(CoffeeScriptとか)へコンパイルされるものを置く場所らしい。
routesファイル上のパスが「/」だと、「http://localhost:9000/
」にしかマッチしない。
「/zzz」だと「http://localhost:9000/zzz
」にマッチする。
routes | マッチするURIの例 | コントローラーの記述例 | |
---|---|---|---|
パス | メソッド呼び出し | ||
/ |
controllers.Application.index |
|
def index = Action { Ok("root") } |
/zzz |
controllers.Application.zzz0 |
http://localhost:9000/zzz |
def zzz0 = Action { Ok("zzz") } |
/zzz/:id |
controllers.Application.zzz1(id) |
http://localhost:9000/zzz/aaa |
def zzz1(id: String) = Action { |
/zzz/*id |
controllers.Application.zzz1(id) |
http://localhost:9000/zzz/aaa |
|
/zzz/:id1/*id2 |
controllers.Application.zzz2(id1, id2) |
http://localhost:9000/zzz/aaa/bbb |
def zzz2(id1: String, id2: String) = Action { |
パスの部分に文字列を書くと、それに完全一致するものだけマッチする。
「:
」から始めると、スラッシュ「/」で区切られた文字列1つを入れる変数になる。
「*
」から始めると、スラッシュ「/」も含めてそれ以降全部を入れる変数になる。
どのビューへ遷移するかを決めるのがコントローラーとアクション。
たぶん複雑なロジックもここに書く。
package controllers
import play.api._ import play.api.mvc._
object Application extends Controller { def index = Action { Ok(views.html.index("Your new application is ready.")) } }
Actionは、play.api.mvc.Actionオブジェクトのapplyメソッド呼び出し。
(Scalaではapplyメソッドはメソッド名自体が省略できる。また、引数が1つであれば丸括弧でなく波括弧が使える)
OkはScalaの文法的にはよく分からない(爆)が、HTTPレスポンスの「200
OK」を返すもの。
以下の様にボディー部を記述できる。
def index = Action { Ok("test") }
ボディー部をplay.api.templates.Htmlクラスで指定すると、HTMLを記述できる。
def index = Action { Ok(new Html("<strong>test</strong>")) }
で、実用上はHTMLを直接記述するのではなく、ビュー(テンプレート)を指定する。
def index = Action { Ok(views.html.index("Your new application is ready.")) }
ActionはHTTPリクエストを引数に取ることが出来る。
ソース | アクセス方法(URL) | 表示されるもの |
---|---|---|
def index = Action { request => Ok("request=[%s]".format(request)) } |
http://localhost:9000 |
request=[GET /] |
http://localhost:9000/?abc=123 |
request=[GET /?abc=123] |
|
def index = Action { request => Ok("zzz=" + request.queryString.getOrElse("zzz", "")) } |
http://localhost:9000 |
zzz= |
http://localhost:9000/?zzz=abc |
zzz=Buffer(abc) |
|
http://localhost:9000/?zzz=abc&zzz=def |
zzz=Buffer(abc, def) |
request.queryStringの型は、Map[String,Seq[String]]
。
クエリーのパラメーター名をキーとし、その一覧(Seqだが、実体はBufferらしい)を返す。
ビューはテンプレート(HTMLファイルのようなもの)で記述する。
基本はHTMLだが、「@」を付けてScalaの文を書ける。
@(message: String) @main("Welcome to Play 2.0") { @play20.welcome(message) }
テンプレートはScalaのオブジェクトに変換されるようだ。
「views/index.scala.html
」→「views.html.index
オブジェクト」
テンプレートでは、1行目が「そのテンプレートへの引数」になる。
@(message: String)
↓(このように変換されると思われる)
def apply(message: String) = 〜
サンプル(雛形)では、コントローラーから以下の様に引数を1つ指定して呼び出している。
def index = Action { Ok(views.html.index("Your new application is ready.")) }
1行目以外の「@」は、Scalaの式(メソッド呼び出し等)になる。
@main("Welcome to Play 2.0") { @play20.welcome(message) }
「@main(title){ content }
」は、mainオブジェクト(のapplyメソッド)の呼び出し。
引数リストが2つある形式となっている。ここでは、最初の引数は丸括弧、後の引数は波括弧でくくられている(
引数が1つずつしか無いので、文法上は丸括弧でも波括弧でもどちらでもOK)。
(play20.welcomeもPlay2.0で用意されたwelcomeオブジェクトの呼び出し)
@(title: String)(content: Html) 〜
index.scala.htmlをもっと単純なものに変えてみると分かりやすい。
@(message: String) <html> <head> <title>@message</title> </head> <body> <p>@message</p> </body> </html>
HTMLの中に可変部だけ@付きで変数を書いているような感じになる。
したがって、HTMLエディターを使ってテンプレートを書くことが出来る。
一番上の行だけちょっと変だし、スタイルシート等のパスもPlay!2.0形式で書いちゃうと正しい場所を指せないけどね(苦笑)
「@
」からScalaの文が始まるが、どこで終わるかについては自動的に判別してくれる。
「@(
〜)
」のように丸括弧で囲むと、その内部で演算などの式も書ける。
「@{
〜}
」のように波括弧で囲むと、その内部で複数の文が書ける。
「@@
」でアットマークの文字そのものを記述(エスケープ)できる。(メールアドレスを「hoge@@hoge.com
」と書く等)
サーバーサイドコメントは「@*
〜*@
」。
forループなんかも書くことが出来る。(自動でyieldが付く扱いになるらしい)
<ul> @for(i <- 0 until 4) { <li>@message @(i + 1)</li> } </ul>
こういう風になってくると、HTMLエディター上では乱れてくるけど(苦笑)
@ifとか@importとかサブルーチン作成(ブロックの再利用)とか色々あるので、テンプレートの説明は必見。