Pergunta

From what I understand controllers in play are singletons, so I'm not sure how to go about this.

In Rails I could simply load a user in the base_controller, and then in any controller that inherits from the base_controller the user object would be available for me to use.

In play, I'm not sure how this will work. Basically in each Action in a controller I want the user object to be available for me.

def someAction = {
    val name = user.name
    val age = user.age
    Ok("hello")
}

Is this possible in play? I'm' sure it is but I can't seem to figure out way to do this.

Foi útil?

Solução

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 UserActions, 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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top