t2v / action-zipper   0.2.0

GitHub

Play2 ActionBuilder Composition Support

Scala versions: 2.10 2.11 2.12

ActionZipper Build Status

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.")))
  }

}

Motivation

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.

Installation

Add dependency declarations into your Build.scala or build.sbt file:

libraryDependencies += "jp.t2v" %% "action-zipper" % "0.2.0"

Target

  • Scala 2.11.x & Scala 2.12.x
  • Play 2.6.x

Alias

any and anyAsync

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) =>

More Example

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

}