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 ActionBuilder
s 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"))
}
}