Documentation

You are viewing the documentation for the 2.2.0 release in the 2.2.x series of releases. The latest stable release series is 2.4.x.

§サブプロジェクト

複雑なプロジェクトを、一つの Play アプリケーションにまとめる必要はありません。大きなプロジェクトは、小さなアプリケーションに分割できます。また、アプリケーションから独立したロジックは Java や Scala ライブラリに切り出すのもよいでしょう。

詳細については「マルチプロジェクト・ビルドについての SBT ドキュメント」 (原文) を参照してください。また、サブプロジェクトを定義するにあたって最も基本的なこととして、サブプロジェクト用のビルドファイルというものはありません。親のビルドファイルにサブプロジェクトを定義します。

§ライブラリをサブプロジェクトとして切り出す

アプリケーションからシンプルな「ライブラリプロジェクト」を切り出すことができます。build.sbt に、次のような sbt のプロジェクト定義を追加してください。

import play.Project._

import play.Project._

name := "my-first-application"

version := "1.0"

playScalaSettings

lazy val myLibrary = project

最終行の小文字の project は、代入先の val の名前を使ってプロジェクトの名前とフォルダを決定する Scala マクロです。

上記の例では myLibrary ディレクトリにサブプロジェクトを定義しました。サブプロジェクトは普通の sbt プロジェクトの一種であり、標準的なディレクトリ構成に従います。

myProject
 └ app
 └ conf
 └ public
myLibrary
 └ src
    └ main
       └ java
       └ scala
project
 └ Build.scala

ビルド設定でサブプロジェクトを有効にした場合、それぞれのプロジェクトを個別にコンパイル、テスト、実行することができます。Play コンソールで projects コマンドを実行すると、全てのプロジェクトが表示されます。

[my-first-application] $ projects
[info] In file:/Volumes/Data/gbo/myFirstApp/
[info] 	 * my-first-application
[info] 	   my-library

デフォルトのプロジェクトは変数名がアルファベット順で最初の物になります。メインプロジェクトを指定したい場合は変数名を aaaMain 等にする事で可能になります。現在のプロジェクトを切り替えるには、project コマンドを使ってください。

[my-first-application] $ project my-library
[info] Set current project to my-library
>

Play アプリケーションを開発モードで起動している場合、依存するサブプロジェクトも自動的に再コンパイルされます。サブプロジェクトのコンパイルエラーも、ブラウザ上で確認できます。

§Webアプリケーションを複数のプロジェクトに分割する

Play アプリケーションはデフォルト設定に従った普通のsbtプロジェクトでもあるため、お互いに依存性を持たせることができます。

以下の例では play.Project を定義するために build.scala ファイルを使用します。このアプローチは 2.2 より前のバージョンにおいて Play アプリケーションを定義する方法でした。このアプローチは後方互換性のために残されています。build.sbt に基づいたアプローチに移行することをお勧めしますが、build.scala を使う場合は sbt の Project 型と project マクロを使ってください。

サブプロジェクトを play.Projet として設定してみましょう:

import sbt._
import Keys._
import play.Project._

object ApplicationBuild extends Build {

  val appName = "zenexity.com"
  val appVersion = "1.2"

  val common = play.Project(
    appName + "-common", appVersion, path = file("common")
  )
  
  val website = play.Project(
    appName + "-website", appVersion, path = file("website")
  ).dependsOn(common)
  
  val adminArea = play.Project(
    appName + "-admin", appVersion, path = file("admin")
  ).dependsOn(common)
  
  val main = play.Project(
    appName, appVersion, path = file("main")
  ).dependsOn(
    website, adminArea
  )
}

これで、Web サイトと管理者向けサイトから構成される main プロジェクトを定義できました。また、両方のプロジェクトが common モジュールに依存しています。

main プロジェクトを再コンパイルしてテストするとき、依存するプロジェクトが再コンパイルされてテストされるようにしたい場合は、“aggregate” 句を追加する必要があります。

val main = play.Project(
  appName, appVersion, appDependencies
).dependsOn(
  website, adminArea
).aggregate(
  website, adminArea
)

ノート: 名前の衝突を避けるため、サブプロジェクトのコントローラは、アセットのコントローラーも含め、メインプロジェクトと別の名前空間を使用するようにして下さい。

§ルートファイルを分割する

play 2.1 からはルートファイルを小さな部品に分割することもできます。これはロバストで再利用可能な、マルチモジュールの play アプリケーションを作成したい時にとても便利な機能です。

§以下のビルドファイルを考えます

project/Build.scala:

import sbt._
import Keys._
import play.Project._

object ApplicationBuild extends Build {

    val appName         = "myproject"
    val appVersion      = "1.0-SNAPSHOT"

    val adminDeps = Seq(
      // Add your project dependencies here,
       "mysql" % "mysql-connector-java" % "5.1.18",
      jdbc,
      anorm
    )

    val mainDeps = Seq()
  
    lazy val admin = play.Project(appName + "-admin", appVersion, adminDeps, path = file("modules/admin"))


    lazy  val main = play.Project(appName, appVersion, mainDeps).settings(
      // Add your own project settings here      
    ).dependsOn(admin).aggregate(admin)

}

§プロジェクト構成

app
  └ controllers
  └ models
  └ views
conf
  └ application.conf
  └ routes
modules
  └ admin
    └ conf/admin.routes
    └ app/controllers
    └ app/models
    └ app/views     
project
 └ build.properties
 └ Build.scala
 └ plugins.sbt

ノート: application.conf は一つしかありません。また admin のルートファイルは admin.routes という名前になっています。

conf/routes:

GET /index                  controllers.Application.index()

->  /admin admin.Routes

GET     /assets/*file       controllers.Assets.at(path="/public", file)

modules/admin/conf/admin.routes:

GET /index                  controllers.admin.Application.index()

GET /assets/*file           controllers.admin.Assets.at(path="/public", file)

§アセットとコントローラクラスは controllers.admin パッケージ以下に無ければなりません。

modules/admin/controllers/Assets.scala:

package controllers.admin
object Assets extends controllers.AssetsBuilder

ノート: Java ユーザは以下のように類似のことができます。

// Assets.java
package controllers.admin;
import play.api.mvc.*;

public class Assets {
  public static Action<AnyContent> at(String path, String file) {
    return controllers.Assets.at(path, file);
  }
}

コントローラも同様です:

modules/admin/controllers/Application.scala:

package controllers.admin

import play.api._
import play.api.mvc._
import views.html._

object Application extends Controller {

  def index = Action { implicit request =>
    Ok("admin")
  }
}

§admin でのリバースルーティング

通常のコントローラの場合は以下のように呼び出します:

controllers.admin.routes.Application.index

Assets の場合は以下のようになります:

controllers.admin.routes.Assets.at("...")

§ブラウザ経由の場合

http://localhost:9000/index

は以下を呼び出します。

controllers.Application.index

また

http://localhost:9000/admin/index

は以下を呼び出します。

controllers.admin.Application.index