Scala Advent Calendar2011: Play2.0 + Scala
この記事は、Scala Advent Calendar JP 2011 の16日目です。
【お断り】Play 2.0はまだベータ版です。将来仕様変更が行われて、下記の操作がそのまま動かなくなる可能性があります。
相次いで、Typesafe StackやHerokuでのサポート表明がされるなど、期待のWEBフレームワーク Play 2.0(beta) + Scalaを駆け足でめぐります。
なにはともあれ、インストールします
ダウンロードして、展開して、パスを通しておきましょう。アーカイブはこちらから
http://download.playframework.org/releases/play-2.0-beta.zip
新規Scalaアプリケーション「MyApp」を作成します
> play new MyApp
What is the application name?
> MyAppWhich template do you want to use for this new application?
1 - Create a simple Scala application
2 - Create a simple Java application
3 - Create an empty project> 1
OK, application MyApp is created.
Have fun!
以上の操作で、MyAppフォルダとその中に幾つかのフォルダやファイルが生成されます。
すぐに、サーバを起動します
2.0からSBTベースになりました。
カレントディレクトリを変更して
> cd MyApp
playコンソールを実行します。
> play
そして起動!
[MyApp] $ run
- (Running the application from SBT, auto-reloading is enabled) ---
[info] play - Listening for HTTP on port 9000...
(Server started, use Ctrl+D to stop and go back to the console...)
以上でサーバが起動しました。
少しコントローラをいじってみます
デフォルトのコントローラクラスファイル「app/controllers/Application.scala」
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.")) } }
の、index関数の下に、新しい関数を追加します。
def hello = Action { Ok("Hello Play World!") }
ルーティング定義ファイル「conf/route」に以下の行を追加します。
GET /hello controllers.Application.hello()
以下のURLをロードするだけです。
http://localhost:9000/hello
コンパイルは不要です。
引数を渡せるようにしてみましょう
まずは、コントローラの修正
def hello(name:String) = Action { Ok("Hello "+ name +" World!") }
次にルーティングの修正
GET /hello/:name controllers.Application.hello(name:String)
引数が文字列型(のまま)の場合は型を省略できるので、以下でもOKです。
GET /hello/:name controllers.Application.hello(name)
確認してみましょう。
http://localhost:9000/hello/Scala
ただし2バイト文字を使うと・・・
http://localhost:9000/hello/スカラ
Hello %E3%82%B9%E3%82%AB%E3%83%A9 World!
のように、・・・URLエンコードされたまま・・・になります。
ので、URLデコードしてあげましょう。
def hello(name:String) = Action { Ok("Hello "+ java.net.URLDecoder.decode(name) +" World!") }
確認してみましょう・・・
http://localhost:9000/hello/日本語
Hello 繧ケ繧ォ繝ゥ World!
あぁ・・今度は、文字化け・・・orz
今は単純なテキストとして帰っているので、HTMLとして返してあげましょう。
ここでは、テンプレートを使って簡単にHTML化します。
まずは app/views/index.scala.htmlを使いまわします。
コントローラだけの修正です。
def hello(name:String) = Action { Ok(views.html.index("Hello "+ java.net.URLDecoder.decode(name) +" World!")) }
ひとまず文字化け解消したと思います。
こんどは、独自のテンプレートを作りましょう
app/views/hello.scala.htmlを作成します。
まずはシンプルバージョンです。
@(message:String) @main("Hello") { @message }
上記の簡単は意味は、
- 文字列messageを引数にとって、
- main.scala.htmlを"hello"とブロックを引数にして展開した結果を表示する
です。
コントローラも修正して、読み込むテンプレートを変更しましょう。
def hello(name:String) = Action { Ok(views.html.hello("Hello "+ java.net.URLDecoder.decode(name) +" World!")) }
テンプレートをいじってみましょう
メッセージを10回繰り返します。
@main("Hello") { @for(i <- (1 to 10)) { @message<br /> } }
コントローラに渡す引数をひとつ増やして、繰り返し回数を指定できるようにしてみます
@(message:String, num:Int) @main("Hello") { @for(i <- (1 to num)) { @message<br /> } }
def hello(name:String, num:Int) = Action { Ok(views.html.hello("Hello "+ java.net.URLDecoder.decode(name) +" World!", num)) }
GET /hello/:name/:num controllers.Application.hello(name, num:Int)
実験してみましょう。
http://localhost:9000/hello/日本語/6
実は、今の状態だと・・・
http://localhost:9000/hello/日本語
や
は受け付けなくなっています。
これに対応するには、ルーティングファイルで引数の初期値を以下のように修正します。
GET /hello controllers.Application.hello(name="Play", num:Int=10)
GET /hello/:name controllers.Application.hello(name, num:Int=10)
GET /hello/:name/:num controllers.Application.hello(name, num:Int)
注:上からマッチングが行われるので、順番が重要です。
RESTでなく、普通に?以下のパラメータを受け取る事も出来ます
GET /hello controllers.Application.hello(name, num:Int)
これとデフォルト引数を組み合わせることできます。
GET /hello controllers.Application.hello(name ?= "Play", num:Int ?= 10)
上記の設定の場合は
http://localhost:9000/hello?name=scala&num=12
といったURLになります。
サーバの終了するには
サーバはCtrl+Dで終了できます。
コンソールはexitで終了します。
参考サイト
Play2.0のホーム http://www.playframework.org/2.0
API http://playframework.github.com/api/scala/#package
ソースとドキュメント https://github.com/playframework/Play20/wiki/ScalaHome
Play2.0ホームの日本語訳 http://playdocja.appspot.com/2.0