Reputation: 9761
I'm starting to learn Play,
and i'm stuck in trying to understand how Action is implemented. I just don't understand the language construct and that really frustrate me.....
I don't understand how one can write ?
val echo = Action { request => Ok("Got request [" + request + "]") }
And have it compile .... What kind of construct is that ? It would be a case class that take as parameter a function, i might have.....
But here is the definition of Action at https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/play/api/mvc/Action.scala
Which basically state that Action is a function object Trait that either takes a requestHeader or a Request by virtue of the apply taken from Essential action and the one that it defines itself....
/**
* An `EssentialAction` underlies every `Action`. Given a `RequestHeader`, an
* `EssentialAction` consumes the request body (an `Array[Byte]`) and returns
* a `Result`.
*
* An `EssentialAction` is a `Handler`, which means it is one of the objects
* that Play uses to handle requests.
*/
trait EssentialAction extends (RequestHeader => Iteratee[Array[Byte], Result]) with Handler {
/**
* Returns itself, for better support in the routes file.
*
* @return itself
*/
def apply() = this
}
/**
* Helper for creating `EssentialAction`s.
*/
object EssentialAction {
def apply(f: RequestHeader => Iteratee[Array[Byte], Result]): EssentialAction = new EssentialAction {
def apply(rh: RequestHeader) = f(rh)
}
}
/**
* An action is essentially a (Request[A] => Result) function that
* handles a request and generates a result to be sent to the client.
*
* For example,
* {{{
* val echo = Action { request =>
* Ok("Got request [" + request + "]")
* }
* }}}
*
* @tparam A the type of the request body
*/
trait Action[A] extends EssentialAction {
/**
* Type of the request body.
*/
type BODY_CONTENT = A
/**
* Body parser associated with this action.
*
* @see BodyParser
*/
def parser: BodyParser[A]
/**
* Invokes this action.
*
* @param request the incoming HTTP request
* @return the result to be sent to the client
*/
def apply(request: Request[A]): Future[Result]
def apply(rh: RequestHeader): Iteratee[Array[Byte], Result] = parser(rh).mapM {
case Left(r) =>
Play.logger.trace("Got direct result from the BodyParser: " + r)
Future.successful(r)
case Right(a) =>
val request = Request(rh, a)
Play.logger.trace("Invoking action with request: " + request)
Play.maybeApplication.map { app =>
play.utils.Threads.withContextClassLoader(app.classloader) {
apply(request)
}
}.getOrElse {
apply(request)
}
}(executionContext)
I'm not able to reproduce that myself, with a simple case it does not compile that is damn strange....
Upvotes: 1
Views: 377
Reputation: 482
In scala, we can invoke Action with a function block:
Action { request => ..... }
This is rewritten as:
Action.apply({ request => ... })
You may be wondering what the implicit keyword is doing. It's a shorthand convenince to make the argument to a function available on the implciit scope within the function. In other words:
Action apply { implicit request => ... }
is the same as:
Action apply { request => implicit val _some_random_name_ = request ... }
Quoted from here: https://groups.google.com/forum/#!topic/scala-user/sR-FD3eiUcQ
Upvotes: 1
Reputation: 179098
What you need to look at is the Action
object and this apply
method which it inherits.
Upvotes: 2