PlayFramework/チュートリアル+α のバックアップ差分(No.1)
更新- 追加された行はこの色です。
- 削除された行はこの色です。
[[公開メモ]] * Play Framework [#h8db752b] http://www.playframework-ja.org/ Java あるいは Scala ベースで開発できる軽量 Web アプリケーションフレームワークだそうで、 面白そうだったのでさわってみました。 Debian squeeze 上で、環境は LANG:console $ java -version java version "1.6.0_18" OpenJDK Runtime Environment (IcedTea6 1.8.13) (6b18-1.8.13-0+squeeze2) OpenJDK Client VM (build 14.0-b16, mixed mode, sharing) です。 Scala を開発言語としていじってみます。 以下、私自身は Ruby on Rails の経験があったため、 この手のフレームワークを始めてさわる人向けではない記述になっていると思いますが、 ご了承下さい。 * インストール&チュートリアル [#xc603da6] Java 環境が揃っていれば、あとは .zip ファイルを落としてきて展開するだけというお手軽インストールで、 Play 2.0 のインストール~ http://www.playframework-ja.org/documentation/2.0.4/Installing 初めての Play アプリケーション (Scala 版)~ http://www.playframework-ja.org/documentation/2.0.4/ScalaTodoList を見れば、チュートリアルを追うところまでは迷うところはありませんでした。 - コンパイルが必要な言語で開発を行っているにもかかわらず、ブラウザで再読込するだけで ソースの変更を自動で検出してシームレスにアプリケーションをアップデートしてくれる - その際、コンパイルエラーもブラウザ上で確認可能 - エボルーション(Rails におけるマイグレーション)までブラウザから行える - 生の SQL を基本としているので参入障壁が低い あたりはさすが後発なだけあると思いました。 * チュートリアルに手を加える [#w7e6f770] 以下、さらにもう少し様子をうかがうために、チュートリアルで作成した todolist アプリケーションに機能を追加してみることにします。 * task に登録日時を記録する [#a7dbae77] ** データベースに該当するカラムを追加 [#l34f6968] データベース形式の変更は、その履歴をちゃんとバージョン管理するために、 エボルーションを利用します。 conf/evolutions/default/2.sql LANG:sql # Tasks schema # --- !Ups ALTER TABLE task ADD COLUMN registered DATETIME NOT NULL; # --- !Downs ALTER TABLE task DROP COLUMN registered; チュートリアルのまま H2 を使っているので、SQL 文法は~ http://www.h2database.com/html/main.html ~ を参考にしました。 ブラウザから todolist ページを再読込すると、 Database 'default' needs evolution! An SQL script will be run on your database - [Apply this script now!] としてエボルーションするかどうかを聞かれるので、 [Apply this script now!] を押すと、データベースが更新される。 ** モデルの変更 [#g4d853c3] クラスに対応するメンバーを追加する。 app/models/Task.scala LANG:scala case class Task( id: Long, label: String, registered: java.util.Date ) registered の型は NULL を許容するのであれば Option[java.util.Date] とするらしいけれど、 今の場合は NOT NULL を指定してあるので生の java.util.Date とした。 ** Anorm パーサーの変更 [#t2421e3d] データベースの行データを Task クラスのインスタンスへ変換するためのパーサーを registered に対応するよう書き直します。 Anorm によるシンプルなデータアクセス~ http://www.playframework-ja.org/documentation/2.0.4/ScalaAnorm ~ の「Parser API の利用」を参照しました。 app/models/Task.scala LANG:scala object Task { val task = { get[Long]("id") ~ get[String]("label") ~ get[java.util.Date]("registered") map { case id~label~registered => Task(id, label, registered) } } def all(): List[Task] = DB.withConnection { implicit c => SQL("select * from task").as(task *) } val task の部分でパーサーを定義して、それを all() の中の .as(task *) の部分で使っています。 SQL("select * from task") が返す行データを task パーサーで変換して List[Task] 型として返しているのが all() になります。 task の中身は、id, label, registered の値を使って Task(id, label, registered) を作成して返しているのですが、 私自身この部分の細かい文法はまだ理解できていません。 とりあえず呪文としては基本的な使い方を理解しました。 ** INSERT 文に registered を与える [#hf439822] registered に NOW() を与えるだけです。 app/models/Task.scala LANG:scala def create(label: String) { DB.withConnection { implicit c => SQL( """ INSERT INTO task (label, registered) VALUES ({label}, NOW()) """ ).on( 'label -> label ).executeUpdate() } } ** 一覧に登録日を表示する [#sc2ec10a] app/views/index.scala.html LANG:scala @main("Todo list") { <h1>@tasks.size task(s)</h1> <ul> @tasks.map { task => <li> @task.label (@task.registered) @form(routes.Application.deleteTask(task.id)) { <input type="submit" value="Delete"> } </li> } </ul>
Counter: 8017 (from 2010/06/03),
today: 1,
yesterday: 0