On Github jamesward / introduction_to_the_play_framework-scala
Create a New Play App
activator new
IDE Support
activator idea
Run the App
activator ~run
Open the App
http://localhost:9000VERB PATH CONTROLLER_METHOD GET / controllers.Application.index() GET /foo controllers.Application.foo()
def index = Action { Ok(index.render("Your new application is ready.")) }
@(message: String) @main("Welcome to Play 2.0") { @message }
Run All Tests Once
activator test
Run All Tests Continuously
activator ~test
Run One Test
activator "test-only my.namespace.MySpec"
Run Failed Tests
activator test-quick
"render index template" in new WithApplication { val html = views.html.index("Coco") contentAsString(html) must contain("Hello Coco") }
object FunctionalExampleControllerSpec extends PlaySpecification { "respond to the index Action" in new WithApplication { val result = controllers.Application.index()(FakeRequest()) status(result) must equalTo(OK) contentType(result) must beSome("text/plain") contentAsString(result) must contain("Hello Bob") } }
"respond to the index Action" in new WithApplication { val Some(result) = route(FakeRequest(GET, "/Bob")) status(result) must equalTo(OK) contentType(result) must beSome("text/html") charset(result) must beSome("utf-8") contentAsString(result) must contain("Hello Bob") }
case class Foo(name: String) object Foo { implicit val fooFormat = Json.format[Foo] }
def foo = Action { Ok(Foo("asdf")) }
object Foo { implicit val fooWrites = Json.writes[Foo] implicit val fooReads: Reads[Foo] = (__ \ "name").read[String](minLength[String](5)).map(Foo(_)) } Json.parse("""{"name": "asdf"}""").validate[Foo] // JsError(List((/name,List(ValidationError(error.minLength,WrappedArray(5))))))
val foo = Json.obj("name" -> "Bob") val transformer = (__ \ "name").json.put(JsString("foo")) val newFoo = foo.transform(transformer) newFoo.map(Ok(_)).getOrElse(BadRequest)
val js = json"""{ "foo" : "bar", "foo2" : 123 }""" js match { case json"""{ "foo" : $a, "foo2" : $b }""" => Some(a -> b) case _ => None }
addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0")assets/javascripts/foo.coffee
<script src='@routes.Assets.at("javascripts/foo.min.js")'></script>
"org.webjars" % "jquery" % "2.1.1"Use a WebJar
<script src='@routes.Assets.at("lib/jquery/jquery.min.js)'></script>
def foo = Action { Ok("foo") }
def foo = Action.async { Future(Ok("foo")) }
def pause(duration: Int) = Action.async { Promise.timeout(Ok(duration.toString), duration seconds) }
val futureResponse: Future[Response] = WS.url("http://www.foo.com").get
def foo = Action.async { val futureResponse = WS.url("http://www.foo.com").get futureResponse.map { response => Ok(response.body) } }
def foo = Action.async { val futureJW = WS.url("http://www.jamesward.com").get val futureTwitter = WS.url("http://www.twitter.com").get for { jw <- futureJW twitter <- futureTwitter } yield Ok(jw.response.body + twitter.response.body) }
def events = Action { val (enumerator, channel) = Concurrent.broadcast[String] Akka.system.scheduler.schedule(Duration.Zero, 1.second, new Runnable { def run() = channel.push("hello") }) Ok.feed(enumerator &> EventSource()).as(EVENT_STREAM) } $ -> events = new EventSource("/events") events.onmessage = (e) -> console.log(e.data)
def echoWs = WebSocket.using[String] { request => val (enumerator, channel) = Concurrent.broadcast[String] val in = Iteratee.foreach[String](channel.push) (in, enumerator) } $ -> ws = new WebSocket("ws://localhost:9000/echo") ws.onopen = () -> ws.send("foo") ws.onmessage = (message) -> console.log(message.data)