Play2 ActionBuilder Composition Support
package controllers
import play.api.mvc._
import jp.t2v.lab.play2.actzip._
import scala.concurrent.{ExecutionContext, Future}
class Application (cc: ControllerComponents) extends AbstractController(cc) {
private implicit val ec: ExecutionContext = cc.executionContext
val MyAction = AuthAction zip DBTxAction
def index = MyAction.async(parse.json) { case (authRequest, dbRequest) =>
println(authRequest.user)
println(dbRequest.dbSession)
Future.successful(Ok(views.html.index("Your new application is ready.")))
}
}ActionBuilder is Play2 standard action composition system.
It can compose other ActionFunctions that have same Request type.
However, ActionBuilders that have different request type can not compose each other. (for example, AuthenticationAction and DBAction)
Action-Zipper provides the way that make any ActionBuilders enable to compose.
Add dependency declarations into your Build.scala or build.sbt file:
libraryDependencies += "jp.t2v" %% "action-zipper" % "0.2.0"- Scala 2.11.x & Scala 2.12.x
- Play 2.6.x
Since ActionBuilder#apply and ActionBuilder#async are overloaded, we can not use Pattern Matching Anonymous Functions.
// compile error!!
def index = MyAction { case (authRequest, dbRequest) =>So ZippedActionN has any and anyAsync method that can use instead of apply and async
def index = MyAction.any { case (authRequest, dbRequest) =>def index = MyAction.anyAsync { case (authRequest, dbRequest) =>package controllers
import play.api.mvc._
import jp.t2v.lab.play2.actzip._
import scala.concurrent.{ExecutionContext, Future}
class Application (cc: ControllerComponents) extends AbstractController(cc) {
private implicit val ec: ExecutionContext = cc.executionContext
// it can chain more than 2
val Action3 = Action zip Action zip Action
val Action4 = Action zip Action zip Action zip Action
// ZippedAction can zip another ZipedAction
val Action7 = Action3 zip Action4
def index = Action7.any { case (_, _, _, _, _, _, _) =>
Ok(views.html.index("7 action are zipped"))
}
}