コミュニティが寄付した拡張

バージョン互換性

scala-0.6 は、このバージョンでテストされています: Tested with 1.1r902

閲覧

内容

モジュールバージョン

Scala サポート

play 1.1 リリースには、プログラミング言語 Scala のサポートが含まれる予定です。play フレームワークの柔軟なアーキテクチャのおかげで、Scala のサポートはシンプルなモジュールとして提供されます。必要なのは conf/application.conf ファイルで scala モジュールを有効にすることだけです。

module.scala=${play.path}/modules/scala

こうすることで、アプリケーションの全部または一部を scala を使って書くことができるようになります。もちろん Java と混在させることも可能です。

我々はこのモジュールをとてもとても活発に開発しています。このモジュールを実験的な機能として試すことはできます。現時点で完全な play アプリケーションを Scala で書くことは期待しないでください。

scala サポートをざっと眺めてみたい場合は、Scala スクリーンキャスト を見てみてください。

Scala サポートを使って新しいアプリケーションを作成する

play new コマンドの --with オプションを使うことで、scala を使う準備が整ったアプリケーションを自動的に作成することが可能です。とにかく試してみてください:

play new myApp --with scala

play アプリケーションはいつも通り作成されますが、 controllers パッケージを見てみると Application.java ファイルが Application.scala ファイルに置き換えられています:

package controllers
 
import play._
import play.mvc._
 
object Application extends Controller {
  def index = render()
}

これは Java 版のデフォルト Application コントローラととても似ています。

いつものように play run を使ってアプリケーションを実行すれば、いつものウェルカムページが表示されます。ここで render() 呼び出しを置き換えるように Application.scala ファイルを編集してみてください。

def index = "Hello scala!"

ページを更新すると、魔法が見られます。

もっと明白なスタイルが好ましい場合は、レスポンスオブジェクトを直接書くために renderHtml メソッドを使用することができます。

いつも通り、間違いがあった場合、play は完璧な方法でエラーの内容を表示します; (今回、後に続くセミコロンを忘れることは、これまでより難しくなりました)

型の直接返却

上記のように、アクションの結果を送出するために推論された返却型を直接使用することができます。例えば、String を使う場合は以下のようになります:

def index = "<h1>Hello world</h1>"

XHTML をリテラルとして書くために、組込みの XML サポートを使うこともできます:

def index = <h1>Hello world</h1>

返却型がバイナリストリームのように見える場合、play は自動的に renderBinary() を使います。このため、組込みの Captcha ヘルパを使ったキャプチャの生成を、次のように書くことができます:

def index = Images.captcha

アクションパラメータと scala のデフォルト引数

Java と同じやり方で、いくつかのアクションパラメータを宣言することができます:

def index(name: String) = <h1>Hello {name}</h1>

scala の大きな利点は、これらのパラメータにデフォルト値を定義できることです:

def index(name: String = "Guest") = <h1>Hello {name}</h1>

こうすると、もし name HTTP パラメータが見つからない場合、play はデフォルト引数値を使います。

トレイトを使ったコントローラの合成

コントローラは、複数のインターセプタを結び付けるために複数のトレイトを使用することができます。

Secure トレイトを定義しましょう:

package controllers
 
import play._
import play.mvc._ 
 
trait Secure {
  self: Controller =>
  @Before
  def check {
    session("user") match {
      name: String => info("Logged as %s", name)
      _ => Security.login
    }
  }
}

そして、これを Application コントーラで使用することができます:

package controllers
 
object Application extends Controller with Secure {
  def index = "Hello world"
}

モデルの定義とアクセス方法

モデルを java だけではなく、scala でも同様に定義することができます。

Scala モジュールは以下の特性を持っています:

  • すべてのクラスは Model を継承する必要があります
  • フィールドはコンストラクタ引数として定義されます
  • 対となるオブジェクトは QueryOn[T] を継承する必要があります
  • 追加の検索メソッドは対となるオブジェクトに定義されるべきです

以下に例を示します:

@Entity
class User(
  //fields

  @Email
  @Required
  var email: String,

  @Required
  var password: String,
  
  var fullname: String

) extends Model {
    //instance methods
    var isAdmin = false
    override def toString = email
}
object User extends QueryOn[User] {
//extra finder methods (if any) come here
}

モデルに対するクエリの実行

この API は、java のものと本当に似ているので、例えば (対となるオブジェクトを適切に定義していると仮定すれば) User クラスの count を呼び出すだけでユーザの数を数えることができます:

User.count

あるいは、値の紐付けを伴う複雑なクエリを実行する場合、以下のような感じになるでしょう:

QueryOn[Post].find("select distinct p.id from Post p join p.tags as t where t.name in (:tags) group by p.id having count(t.id) = :size", Map("tags" -> tags.toArray, "size" -> tags.size)).fetch

モデルにアクセスする別の手段として play.db.jpa.QueryOn を利用することができるので、先ほどの例を使うと: User.countQueryOn[User].count となります。

通常は、対となるオブジェクトを使ってクエリ機能を提供する (例えば User.count) ことが推奨されます。より包括的な QueryOn アプローチの主な利点は scala と java モデルの両方で動作することです。

キャッシュ API

scala 版の キャッシュ api を使うことで、以下のようにすることができます。

Cache.get[People]("person-key-25") match {case Some(p) => println (p.name); case None => println("boo")}

テスト

ScalaTest サポートは Play に統合されており、例えば以下のようにして、ScalaTest を使って容易に単体、そして機能テストを書くことができます:

class SpecStyle extends UnitFlatSpec with ShouldMatchers {
"Creating a user" should "be succesfull" in {
  val user = new User("bob@gmail.com", "secret", "Bob").save()
  bob = User.find("byEmail", "bob@gmail.com").first
  bob should not be (null)
  bob.fullname should be ("Bob")
 }
}
class RenderMethodsTest extends FunctionalTestCase with Matchers{
  val response = GET("/application/json1")
  response shouldBeOk()
  response contentTypeShouldBe("application/json")
  response charsetShouldBe("utf-8")
  response contentShouldBe("{'name':'guillaume'}")
}

完全な API

Scala コンソール

play-scala には、アプリケーションの様々な層を試すために本当に便利なコンソールが含まれています。

以下に例を示します:

kola:yabe-with-scala phausel$ play scala:console
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.1-unstable-localbuild, http://www.playframework.org
~
15:43:17,805 INFO  ~ Starting /Users/phausel/workspace/play-scala/samples-and-tests/yabe-with-scala
15:43:17,809 INFO  ~ Module secure is available (/opt/local/lib/play-1.1-unstable-r777/modules/secure)
15:43:17,809 INFO  ~ Module scala is available (/Users/phausel/workspace/play-scala/samples-and-tests/yabe-with-scala/../..)
15:43:17,810 INFO  ~ Module crud is available (/opt/local/lib/play-1.1-unstable-r777/modules/crud)
15:43:19,300 WARN  ~ You're running Play! in DEV mode
~
~ Starting up, please be patient
~ Ctrl+D to stop
~
15:43:31,774 INFO  ~ Connected to jdbc:hsqldb:mem:playembed
15:43:33,130 INFO  ~ Application 'Yet Another Blog Engine' is now started !
Welcome to Scala version 2.8.0.Beta1-prerelease (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import models._
import models._

scala> User.count     
res0: Long = 3

コマンドはトランザクション内で実行されるので、モデルの変更は永続化されます。

モジュールラッパ

Play には 2 つのデフォルトモジュール (secure と crud) が含まれており、scala モジュールはこれらのラッパを提供します。例えば CRUDFor トレイトを合成して CRUD コントローラを作ることができます:

object Companies extends Controller with CRUDFor[Company]

同様に、これに Secured トレイトを合成して認証をかけることができます:

object Companies extends Controller with CRUDFor[Company] with Secured

ユーティリティ

play.utils.Java と同じように、scala に特化したヘルパメソッドが play.utils.Scala オブジェクトに格納されています。いくつか例を示します:

import play.utils.Scala._

リソースの自動管理

for (stream <- using (new PipeStream())   {
//do something with stream, close() will be called at the end
}

Elvis 演算子

def nuller:String = null
?(nuller.toLowerCase.substring(1)) match  { case Some(s) =>s;case None=>"oh no" }

URL リーダ

val html = fromURLPath("http://www.playframework.org/@api/play/Play.html").mkString //read and connection timeout can be set too

Scala 版 Yabe

scala 版のブログアプリケーションは play-scala に同梱されており、ここ にあります。

メーラサンプル

Mailer クラスを Scala で書くこともできます。ここ にサンプルがあります。

チュートリアル

チュートリアルは ここ にあります。