在播放动作中隐藏可用

时间:2016-01-29 22:04:52

标签: scala playframework slick

我的应用程序遇到许多不同的dbs,db取决于查询字符串参数。我有一个DatabaseConfigLocator,它接受字符串并返回配置,它工作得很好。我的问题是我想在我的控制器中隐式地为每个请求进行配置。我尝试了两种方法。

class MyController extends Controller{
  implicit def dbConfig(implicit request: RequestHeader): DatabaseConfig[JdbcProfile] = DatabaseConfigLocator.get[JdbcProfile](request.getQueryString("dbName")
}

除非我将其更改为具有相同类型的implicit val,否则我必须编译这个dosn,但是我需要每次请求重新检查查询字符串,所以我不认为{{1将会工作

另一种方法是创建一个动作

implicit val

但隐含在块的范围内不可用,我无法找到任何方式将其作为隐式传递。

我的目标是能够做这样的事情

object IODBAction extends ActionBuilder[Request]{
  def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    implicit def dbConfig(implicit request: RequestHeader): DatabaseConfig[JdbcProfile] = DatabaseConfigLocator.get[JdbcProfile]("blah")
    block(request)
  }
}

或者如果提供者可以在实例化时获得隐含的更好的

class MyController extends Controller {

  def create = {
    Action.async {
      request =>
        ApiResponse {
          for {
            id <- aProvider.save(validRegistrationRequest.toVisitor)
          } yield id
        }
    }
  }
}

class aProvider {
  def save(v: Visitor)(implicit dbConfig: DatabaseConfig[JdbcProfile]): ApiResponse[VisitorId]

}

有关如何处理此问题或是否可以使用播放框架的任何建议?

1 个答案:

答案 0 :(得分:1)

不幸的是,我担心你会遇到一个接受单个参数的动作,所以你需要坚持标准游戏&#34;动作组合&#34;图案。这在play docs中有相当广泛的记载。

我定义了一个&#34; Context&#34;像这样:

case class Context(dbConfig: DatabaseConfig[JDBCProfile], request: Request[A])
    extends WrappedRequest(request)

然后创建一个这样的自定义动作构建器:

object DBIOAction extends ActionBuilder[Context]{
  def invokeBlock[A](request: Request[A], block: (Context[A]) => Future[Result]) = {
   val dbConfig = DatabaseConfigLocator.get[JdbcProfile]("blah")
   val context = Context(dbConfig, request)
    block(context)
  }
}

然后您应该能够像这样使用它:

def index = DBIOAction { implicit context =>
   // do some stuff. return a result
}

为了简单起见,我将隐式上下文传递给您的服务方法,也许从上下文中提取dbConfig并将其余部分传递给您的DAO。

class FunService { 
    def getSomeData(param1: String)(implicit context: Context) = {
        // do some work, perhaps using context.dbConfig
    }