1

Our Play application uses Slick as a data access layer. This means that in almost every action in our app we need to have both the current Request and Slick's database Session implicitly available on the scope.

I want to write a custom Action to do this so we only need one line to do this. What I want to do is write it in such a way that I can write something like this:

def someAction = DBAction { implicit request, session =>
  // body with implicit request and session on scope

But this is not valid syntax. Using a tuple does not work because it cannot implicitly unpack the tuple in action body. Is it possible to create a custom action that passes multiple implicit arguments to the body? How do I do this?

DCKing
  • 4,253
  • 2
  • 28
  • 43
  • 1
    possible duplicate of [How to make two function parameters as implicit](http://stackoverflow.com/questions/17296436/how-to-make-two-function-parameters-as-implicit) – senia Aug 02 '13 at 09:08
  • There are two ways to achieve that: a curryed action (`Request[AnyContent] => Session => Result` -> See the @DCKing answer below), or a WrappedRequest (see my answer). – Julien Lafont Aug 02 '13 at 09:42

2 Answers2

4

You cannot implicit 2 variables like that.

But your Custom action can return a WrappedRequest (an object which encapsulates the request and your session), and you can define an implicit conversion between this wrapped request and your Session.

Try this example, derived from this class.

sealed case class DBRequest(session: Session, private val request: Request[AnyContent])
  extends WrappedRequest(request)

trait DBController extends Controller {

  // Implicit conversion from DBRequest to Session
  implicit def session(implicit request: DBRequest) = request.session

  def DBAction(action: DBRequest => Result) = Action { request =>
    database.withSession { session =>
      action(DBRequest(session, request))
    }
  }
}

object MyController extends Controller with DBController {

  def myAction = DBAction { implicit request =>
    println(session)
  }
}
Julien Lafont
  • 7,869
  • 2
  • 32
  • 52
  • Great suggestion! I prefer the curried solution better because the code is simpler and doesn't require implicit conversion magic :) – DCKing Aug 02 '13 at 11:25
  • I like this version because it avoids multiple `w => x => y => z`. But your solution works great for "2 levels" Actions! – Julien Lafont Aug 02 '13 at 12:30
2

@senia was right, currying needs to be used to do this. This is actually addressed in the Play docs but it's a recent addition I missed.

For future reference for people looking for this, my custom action now looks like this:

def DBAction(action: Request[AnyContent] => Session => Result) = {
  Action { request =>
    database.withSession { session =>
       action(request)(session)
    }
  }
}

Which I can then use in the following way:

def someAction = DBAction { implicit request => implicit session => /* body */ }
DCKing
  • 4,253
  • 2
  • 28
  • 43