§サブプロジェクト
複雑なプロジェクトを、一つの 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