1

我们的 Play 应用程序使用 Slick 作为数据访问层。这意味着在我们应用程序的几乎每一个动作中,我们都需要在作用域上隐式地同时使用当前Request数据库和 Slick 的数据库。Session

我想写一个自定义Action来做到这一点,所以我们只需要一行来做到这一点。我想做的是以这样的方式写它,我可以写这样的东西:

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

但这不是有效的语法。使用元组不起作用,因为它不能在动作主体中隐式解包元组。是否可以创建将多个隐式参数传递给正文的自定义操作?我该怎么做呢?

4

2 回答 2

4

你不能像那样隐含 2 个变量。

但是您的自定义操作可以返回一个WrappedRequest(封装请求和会话的对象),并且您可以定义此包装请求和会话之间的隐式转换。

试试这个派生自这个的例子。

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)
  }
}
于 2013-08-02T09:40:36.030 回答
2

@senia 是对的,需要使用柯里化来做到这一点。这实际上在Play 文档中得到了解决,但这是我最近错过的一个补充。

为了供寻找此内容的人将来参考,我的自定义操作现在如下所示:

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

然后我可以通过以下方式使用它:

def someAction = DBAction { implicit request => implicit session => /* body */ }
于 2013-08-02T09:40:20.260 回答