Playの実行runコマンドとstartコマンドの話


どうも、えいやです。
今回もScala+Playの話題です。
今回は[前回](http://qiita.com/items/12493df0b3ddda5a7ec1)の続きのようなもんです。

前回はPlayの導入を行いました。
そして最後の方で、play runコマンドとplay startコマンドでテンプレートのアプリケーションを起動しました。

その実行画面がこちらです。

Runでの起動
![Runでの起動画面](https://www.dropbox.com/s/nxgvxl30qc50ppo/Screen%20Shot%202013-01-30%20at%2021.08.51.png?dl=1)

Startでの起動
![Startでの起動画面](https://www.dropbox.com/s/yf0fbibydmnil72/Screen%20Shot%202013-01-30%20at%2021.15.25.png?dl=1)

Runでの実行と、Startでの実行の違いは、Runが開発モードで、Startが製品モードであるということです。

## どうやって切り替わっているのかという話

さて、両者の違いが何処で発生するのか調べてみましょう。
テンプレートのコードを調べることは初学者にとって非常に重要なことだと思います。

このページに使われているControllerとViewは以下のようになっています。

Controller

```scala: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."))
  }
  
}
```

View

```html:app/views/index.scala.html
@(message: String)

@main("Welcome to Play 2.0") {
    
    @play20.welcome(message)
    
}
```

```html: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>
```

Controllerでは制御を行なっていません。
2つのViewのうちmain.scala.htmlは、コンテンツの表示のみを行なっており、怪しいところはありません。
なので、もう一つのviewに注目してみましょう。

すると、一番疑わしいのは、5行目にある次の記述です。

```
    @play20.welcome(message)
```

このplay20.welcomeというのは、viewのようです。
このviewの働きによって、runの時には文字列型のmessageをページの上部に表示しつつPlayのWelcomeページを表示し、startの際には単に与えられた文字列を表示しているのではないでしょうか。

実際にplay20.welcomeの定義を見てみましょう。

まず、テンプレートに含まれているファイルかどうか調べます。

```bash
% grep -ic "welcome" **/*.scala.html 2> /dev/null | grep ":[1-9]"
app/views/index.scala.html:2
```

とくに見つかりません。

ではplayのインストールディレクトリから探してみましょう。

```bash
% ls -l `which play` 
lrwxr-xr-x  1 h_ayabe  wheel  29  1 30 02:46 /usr/local/bin/play -> ../Cellar/play/2.0.4/bin/play
% grep -ic "welcome" /usr/local/Cellar/play/2.0.4/**/*.scala.html 2> /dev/null | grep ":[1-9]"
/usr/local/Cellar/play/2.0.4/libexec/framework/skeletons/java-skel/app/views/index.scala.html:2
/usr/local/Cellar/play/2.0.4/libexec/framework/skeletons/scala-skel/app/views/index.scala.html:2
/usr/local/Cellar/play/2.0.4/libexec/framework/src/play/src/main/scala/views/play20/welcome.scala.html:8 <- こいつじゃね？
/usr/local/Cellar/play/2.0.4/libexec/samples/java/websocket-chat/app/views/chatRoom.scala.html:1
/usr/local/Cellar/play/2.0.4/libexec/samples/scala/websocket-chat/app/views/chatRoom.scala.html:1
```

かかりました。

```
/usr/local/Cellar/play/2.0.4/libexec/framework/src/play/src/main/scala/views/play20/welcome.scala.html
```

というのが使用されているviewのようです。
開いてみると、次のように定義されています。

```html:/usr/local/Cellar/play/2.0.4/libexec/framework/src/play/src/main/scala/views/play20/welcome.scala.html
@(message: String, style: String = "Scala")

@play.api.Play.maybeApplication.filterNot(_.mode != play.api.Mode.Dev).map { _ =>
    
<link rel="stylesheet" media="screen" href="/@@documentation/resources/style/main.css">

<section id="top">
    <div class="wrapper">
        <h1><a href="/@@documentation">@message</a></h1>
        <nav>
            <span class="versions">
                <span>Browse APIs</span>
                <select onchange="document.location=this.value">
                    <option selected disabled>Select language</option>
                    <option value="/@@documentation/api/scala/index.html">Scala</option>
                    <option value="/@@documentation/api/java/index.html">Java</option>
                </select>
            </span>
        </nav>
    </div>
</section>

<!--- 中略 -->
    
}.getOrElse {
    
<h1>@message</h1>
    
}
```

なるほど、ビンゴじゃねーの。

どうやら、

```
@play.api.Play.maybeApplication.filterNot(_.mode != play.api.Mode.Dev).map { _ =>
	開発モードのページ表示
}.getOrElse {
	製品モードのページ表示
}
```

となっているようです。

これでいつでも製品版と開発版でViewを変更させることが出来るようになりましたね。

以上です。