yabeチュートリアル その1 プロジェクトを始める

Play frameworkのscala-moduleを使ったチュートリアルを和訳します。

本記事では、Page not found — Playframeworkを和訳します。

尚、私の環境は、

です。
playとscala-moduleのバージョンはあっていないと正しく動かないので、気をつけてください。

はじめに

このチュートリアルでは、Scala言語を使って、Playフレームワークベースのアプリケーションの開発を一通り学習することができます。このアプリでは、実際のプロジェクトで必要とされるであろう、全てのことを試すことができます。

このチュートリアルはいくつかの独立した章に分割しています。それぞれの章で、実際のプロジェクトで必要とされる、バリデーションや、エラーハンドリング、セキュリテリ対策、自動テスト、 shiny web interface、管理漁期などなどの、より複雑な機能を紹介しています。

このチュートリアル内の全てのソースコードは、実際のプロジェクトで使ってもらって構いません。We encourage you to copy and paste snippets of code or steal whole chunks.

プロジェクト

チュートリアルのプロジェクとして、「yet another blog engine(ちょっと気の利いたブログエンジン)」を選択しました。あまり想像力に富んだ選択とは言えないけど、今どきのWEBアプリに求められているほとんどの機能を紹介することができます。

編集者や管理者といったいくつかの違う権限ユーザを管理することで、このブログエンジンをより面白くすることができます。

このブログエンジンプロジェクトを「yabe」と呼ぶことにします。
f:id:teppei-studio:20110607123505p:image

このチュートリアルは、サンプルアプリケーションとして提供されています。ソースコードは、Scalaモジュールがインストールされているディレクトリの、samples-and-tests/yabe/ 配下にあります。

PlayFrameworkのインストール

インストールはとても簡単です。ダウンロードページからバイナリパッケージをダウンロードして、それを解凍して適当なところに配置してください。Scalaモジュールは、Playフレームワークのバージョン1.2以上からのみに対応となりますので、気をつけてください。

Windowsの場合は、c:\Documents And Settings\user\play のように、パスの中にスペース文字を含めず、c:\play とした方が賢明です。

効率的に作業するために、PlayディレクトリにPathを切っておく方がいいでしょう。これで、playとコマンドプロンプトに入力するだけで、playユーティリティを使うことができます。インストールがうまく行っていることを確認するために、playと打ってみましょう。基礎的な使い方についてのヘルプ画面が表示されます。




Scalaモジュールをインストール

ScalaでPlayFrameworkを使うのは簡単で、Scalaモジュールをダウンロードするだけです。play install scalaとコマンドを実行するだけで以下のようにインストール可能です。

$ play install scala
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2, http://www.playframework.org
~
~ Will install scala-0.9
~ This module is compatible with: Play 1.2
~ Do you want to install this version (y/n)? y
~ Installing module scala-0.9...
~
~ Fetching http://www.playframework.org/modules/scala-0.9.zip
~ [--------------------------100%-------------------------] 17313.2 KiB/s   
~ Unzipping...
~
~ Module scala-0.9 is installed!

プロジェクト作成

さて、Playを正しくインストールできたので、ブログアプリケーションを作り始めましょう。Playアプリを作るのはとても簡単で、Playコマンドラインのユーティリティで一通りのことができます。以下のようにコマンドを入力しましょう。

~$ play new yabe --with scala

アプリケーションのフルネームを入力するよう求められるので、Yet Another Blog Engine と入力しましょう。

f:id:teppei-studio:20110607141329p:image

play newコマンドは、yabe/ ディレクトリを作成し、以下の重要なディレクトリやファイルを配置します。

  • app/ ディレクトリは、アプリケーションのコア要素を格納するディレクトリです。.scalaソースファイルが配置されるのもここです。
  • conf/ ディレクトリは、アプリケーションの全ての設定ファイルが格納される。メインとなるのは、application.conf ファイルであり、他にもroutes定義ファイルや、dependencies.ymlファイル、他言語化に使われるmessagesファイルなどが格納される。
  • lib/ ディレクトリには、.jarファイルとしてパッケージされた、ScalaライブラリやJavaライブラリが格納される。
  • public/ ディレクトリには、パブリックに利用できるリソースを格納する。javascriptファイルや、スタイルシート、画像ファイルなどが含まれる。
  • test/ ディレクトリには、アプリケーションの全てのテストコードが含まれる。テストコードは、ScalaTest、もしくはSeleniumテストとして記述される。

このように、conf/dependencies.ymlという依存性を定義するファイルには、Scalaの依存性が自動的に定義されます。

# Application dependencies
 
require:
    - play
    - play -> scala 0.9

Playは唯一のエンコーディングとしてUTF-8を使っているため、全ての定義ファイルがUTF-8でエンコーディングされていることが重要になります。適宜、エディタのエンコーディングを設定してください。

さて、熟練のScalaプログラマなら.classファイルはどこに行くのかと考えるでしょう。答えは「どこにも行かない」です。Playは.classファイルを一切使わず、Scalaソースファイルを直接読み込みます。

これは開発過程において、2つの重要な意味を持ちます。ひとつは、Scalaソースファイルの変更を検出し、実行中に自動的に再読み込みする、ということです。ふたつめは、Exceptionが発生した時に、Playは実際のScalaソースコードをベースとして、エラーレポートを表示させることができる、ということです。

実際には、Playはtmp/ディレクトリにバイトコードキャッシュを保持しますが、大きなアプリケーションの再起動処理を高速化させるためだけのものです。必要とあらば、play clean コマンドによってキャッシュをクリアすることができます。

アプリケーション稼働

さて、新しく作ったアプリケーションを試してみましょう。yabe/ディレクトリ内で、play run コマンドを実行するだけでOKです。Playはアプリケーションをロードして、9000番ポートでWEBサーバを起動します。

f:id:teppei-studio:20110607155947p:image

この新しいアプリケーションがどのようにこのページを表示しているのか見てみましょう。

主な入り口は、conf/routesファイルになります。このファイルでは、全てのアクセス可能なURLを定義します。生成されたroutesファイルを参照すると、最初の「ルート」を確認することができます。

GET		/			Application.index

これは、単純に、/ パスに対するGETリクエストを受け取ると、Application.indexアクションメソッドを呼び出すということを意味します。このケースでは、Application.indexは、controllers.Application.indexへのショートカットとなります。controllersパッケージは暗黙的に解決されます。

スタンドアローンのScalaアプリを作る際には、以下のようにmainメソッドによって入り口を定義されたシングルオブジェクトを一般的には使います。

object Main {
    def main(args: Array[String]) {
        …
    }
}

Playアプリでは、それぞれのURLにくくり付く、いくつかの入り口を持ちます。これをアクションメソッドと呼びます。アクションメソッドは、コントローラという特別なオブジェクトで定義されます。

controllers.Applicationコントローラがどのようなものか見てみましょう。yabe/app/controllers.scalaソースファイルを開きます。

package controllers
 
import play._
import play.mvc._
 
object Application extends Controller {
    
    import views.Application._
    
    def index = {
        html.index("Your new Scala application is ready!")
    }
    
}

play.mvc.Controllerクラスを継承していることに気づきます。

このindexアクションは、このオブジェクトの単なるメソッドとして定義されます。これがアクションメソッドの定義方法です。アクションメソッドは、フレームワークによって、純粋なHTTPレスポンスに暗黙的に変換される値を常に返します。

デフォルトのindexアクションはシンプルです。views.Application.html.indexを呼び出し、そこから生成されるHTMLを応答します。テンプレートを使うのはHTTPレスポンスを生成するのに最も一般的な方法になります。(唯一の方法ではありません)

テンプレートは、/app/viewsに配置された、Scalaソースファイルになります。

テンプレートファイルを見てみましょう。helloworld/app/views/Application/index.scala.htmlを開きます。

@(title:String)
 
@main(title) {
    
    @views.defaults.html.welcome(title)
    
}

テンプレートの中身は実に簡単に見えますね。実際、これは他のテンプレートを呼び出し、Welcomeページを生成しているのです。

一行目はテンプレートのパラメータを定義しています。play.template.Htmlを生成する関数をテンプレートとしているという定義になります。この場合、テンプレートはString型のtitleパラメタを持っていて、テンプレートの型は、(String) => Htmlとなります。

そして、このテンプレートはmainという2つのパラメタ(StringとHtmlブロック)を要求する、別のテンプレートを呼び出します。

mainテンプレートが定義されている、helloworld/app/views/main.scala.htmlを見てみましょう。

@(title:String = "")(body: => Html)
 
<!DOCTYPE html>
<html>
  <head>
    <title>@title</title>
    <link rel="stylesheet" href="@asset("public/stylesheets/main.css")">
    <link rel="shortcut icon" href="@asset("public/images/favicon.png")">
    <script src="@asset("public/javascripts/jquery-1.5.2.min.js")"></script>
  </head>
  <body>
    @body
  </body>
</html>

ここでも一行目はテンプレートのパラメータを定義しています。mainテンプレートの型は(String) (Html) => Htmlになります。

コントローラファイルを編集することで、Playフレームワークがどのようにリロードするかを確認することができます。yabe/app/controllers.scalaを開いて、間違いを埋め込んでみましょう。

def index = html.index()

ブラウザを開いて、リロードしてみてください。Playフレームワークが変更を反映して、アプリケーションコントローラをリロードしようとしていることが確認できます。しかし埋め込んだ間違いのために、コンパイルエラーになります。

f:id:teppei-studio:20110608103936p:image

では、プログラムを修正し、正しく編集しましょう。

def index = {
    Logger.info("Index page has been requested")
    html.index("Your new Scala application is ready!")
}

この時、Playフレームワークはコントローラを正しくリロードし、JVM内の古いコードを置き換えます。「/」 URL宛へのリクエストが発生するたびに、コンソール上に「Index page has been requested」というメッセージが表示されます。

この無駄な行を消すことができます。yabe/app/views/Application/index.scala.htmlテンプレートを編集し、Welcomeメッセージを置き換えましょう。

@main("Home") {
    
    <h1>A blog will be there</h1>
    
}

テンプレートのパラメータを削除したので、コントローラを修正します。

def index = {
    html.index()
}

DBのセットアップ

開発を始める前に、もうひとつやらなければならないことがあります。ブログエンジンにはデータベースが必要です。開発用にPlayフレームワークはH2というスタンドアローンのDB管理システムを持っています。きちんとしたDBに切り替える前に、プロジェクトをスタートするには、ベストな手法となります。アプリケーションの再起動をまたいでデータを保持したいか、そうでないかで、ファイルシステムデータベースか、インメモリデータベースかを選ぶことができます。

最初は、モデルを何回も変更したりテストしたりするため、アプリ起動の度にデータをリフレッシュするインメモリデータベースを使うのがいいでしょう。

データベースをセットアップするために、yabe/conf/application.conf を開いて、以下の行のコメントをはずしてください。

db=mem

コメントを見れば分かるように、JDBC接続に簡単に切り替えることができるし、コネクションプールさえ設定することができる。

さて、ブラウザに戻りwelcomeページをリロードしてみましょう。Playフレームワークはデータベースを自動的にスタートさせます。以下のログが出力されることを確認してください。

INFO  ~ Connected to jdbc:h2:mem:play