I'm not sure you'll be able to make it quite as terse as Rails, but using Play's Action Composition style you can build up something quite flexible.
We start by creating a trait which knows how to build such a user, and wraps a normal Action
, allowing the User to be obtained, and passed into the body:
trait UserAware {
def buildUserFromCookie(request:RequestHeader):Option[User] = {
request.cookies.get("myUserCookie").map { c =>
// Build up a User object from cookie contents
// ...
}
}
def cookieNotFound = Results.InternalServerError("Lost your session cookie :-(")
def UserAction(f: User => Request[AnyContent] => SimpleResult):Action[AnyContent] =
UserAction[AnyContent](BodyParsers.parse.anyContent)(f)
def UserAction[T](bodyParser:BodyParser[T])(f: (User) => Request[T] => SimpleResult):Action[T] = {
Action(bodyParser) { request =>
buildUserFromCookie(request).fold(cookieNotFound) ({ user =>
f(user)(request)
})
}
}
}
I'm going to assume that you have a session cookie that holds sufficient information to be able to recreate a User object. Whatever you need to do within buildUserFromCookie()
is out of scope here.
I've defined two UserAction
wrappers, one delegating to the other. The difference is whether you need a special body parser or not. Below you'll see it in use.
The second UserAction
method is the interesting one - if you supply it with a method that can take a User
and a Request
, it will call it for you after creating the user, or bombing out if it can't find the cookie.
Here it is in use:
object MyController extends Controller with UserAware {
def doSomething = UserAction { implicit user => implicit request =>
Ok(s"The user's name is $user.")
}
def doSomethingJsonish = UserAction(parse.json) { implicit user => implicit request =>
Ok(s"The user's name is $user and their request body is JSON: ${request.body}")
}
}
With the overloaded UserAction
s, you can still use Play's Body Parsers to get access to a nicely-typed request body, and you've got the freshly-created User
available as user
.