Play!2.0始めました(1)
Scala(&Java)で利用可能な" Play framework 2.0 "を始めてみました。
今回は、2012-05-02にリリースされた、バージョン2.0.1を使っています。
Play framework(以下Play)は、フルスタックのWebアプリケーションフレームワークです。
特色やセールスポイントについては、ホームページでアピールされているので、そちらを参照にしていただくとして...
ドキュメントが分かりやすいし、とっつきやすい感じでいいですね。(ただやっぱりScalaは貧弱なmyPCでは重いので、Scalaのためにハイスペックなのを所望。)
個人的な注目点は、下記のとおり。
Scalaで分からないところがあっても、Javaで作っておき、あとで置き換えるといったこともできそうです。Javaに慣れていてScala初心者には歓迎すべきところではないでしょうか。
DBアクセスのところなんかは、簡潔で直感的な記述ができるのが特に良いです。
2.0になって、Scalaが完全に統合されています。これについて、公式サイト(トップページの最下段)にアーキテクチャの変遷についての説明があります。
普通のFWなら単なる設定ファイルとするところを、一部をScalaベース(テンプレート、routesファイルなど)にしてしまうなど、静的型付けに深いこだわりがあるようですね。
以下は、練習で作ってみた、社員リストのコードです。
- app/models/Employee.scala
package models import anorm.{toParameterValue, sqlToSimple, SQL} import anorm.SqlRow import play.api.Play.current import play.api.db.DB class Employee { var number: String = "" var name: String = "" } object Employee { def read(row: SqlRow): Employee = { val o = new Employee o.number = row[String]("number") o.name = row[String]("name") return o } def findLast(limit: Int) = { // dspost=postgresのデータソースID DB.withConnection("dspost") { implicit c => SQL( """ SELECT number, name FROM employee WHERE disabled=false ORDER BY updated DESC limit {limit} """).on('limit -> limit)().map(row => read(row)).toList } } }
- app/controllers/Application.scala
package controllers import models.Employee import play.api.mvc.{Controller, Action} object Application extends Controller { def home = Action { request => Ok(views.html.employeelist(Employee.findLast(30))(lang(request))) } }
- app/views/employeelist.scala.html
@(rows: Seq[Employee])(implicit lang: Lang) <!DOCTYPE html> <html> <body> <ol> @for(row <- rows) { <li>@row.number: @row.name</li> } </ol> </body> </html>
そのほか、使ってみていくつか気づいたことをメモします。
環境:
文字列の外部化と国際化
伝統的な*.propertiesとnative2asciiではなく、UTF-8のテキストファイルを使います。
私もちょうどこの仕組みに切り替えたところなので、ちょっとうれしい。
ただ、仕組み上しかたないとは言え、言語の判定がちょっと面倒。
Controllerのヘルパーメソッド"lang(request)"を使えば、"Accept-Languages"から使用する言語を取り出すことができますが、これをControllerからViewに明示的に渡す必要があるのです。
// Controller側 def search(cond: String): Seq[Record] = {...} def init(cond: String) = Action { request => Ok(views.html.index(search(cond))(lang(request))) } // View側 @(rows: Seq[Record])(implicit lang: Lang) @Messages("reload")
デフォルトで"Accept-Languages"による判定になってくれたほうがうれしいような。
主開発者の方がen言語圏でない(氏の個人サイト)ので、その辺のご理解はあるのではないかと期待します。
Viewのビルド後のリフレッシュ
Viewのhtmlは、classファイルにコンパイルされてから実行されます。
これらはクラスフォルダー(target/scala-2.9.1/classes_managed)でビルドパスに設定されます。
Viewのパラメータを変えた後でControllerのView呼び出し修正すると、Eclipseには更新が直接反映されないので、エラーになってしまいます。
これは、"play eclipsify"、プロジェクトのクリーン(メニュー→プロジェクト→ビルド)、プロジェクトのリフレッシュ、ビルドパスの再設定、のどれかを試すと良いです。(どれが正解か、まだ良く分かりません。)
他のページにエラーがあると全部が使えない
すべてのファイルをコンパイルするので、ページを表示しようとしたとき、そのページ以外にエラーがあった場合でも、コンパイルエラーのためエラー画面が表示されてしまいます。
これはちょっと不便かも。