我正在创建与服务对话的控制器。控制器(基于播放库AbstractController
)接收隐式请求并返回Future[Result]
。服务接收请求并返回Future[Model]
。我有一些要防范模型创建的条件。例如,如果用户没有访问权限,则不应创建任何模型。
def create(): Action[JsValue] = Action(parse.tolerantJson).async { implicit request: Request[JsValue] =>
val modelOpt: Option[Future[Result]] = // I've tried Future[Result] here too
for {
attributes <- (request.body \ "data" \ "attributes").validate[JsObject].asOpt
userOpt = (request.body \ "data" \ "attributes" \ "user-name").validate[String].asOpt
user <- userOpt
model <- service1.createModel(user) // Create Model returns type of Future[Model], so this should flatMap to Model
} yield {
val permission = checkPermission(user) // Returns true or false, depending on if the user is permissioned
(userOpt, permission) match {
case (Some(_), true) => Ok(model)
case (Some(_), false) => Forbidden
case (None, _) => NotFound
case (_, false) => Forbidden
}
}
modelOpt.getOrElse(Future { InternalServerError })
}
但是,编译器抱怨说它期望Option[Future[Result]]
并且收到了Future[Result]
(可能是由于我为modelOpt
提供的类型)。但是,我认为如果Json无法验证,它将给我None
,因此我认为外部类型确实必须是一个Option。谁能告诉我发生了什么事?
答案 0 :(得分:1)
如果您查看特征Option[A]
中方法getOrElse的签名:
final def getOrElse[B >: A](default: => B): B
它会解开Option
以返回A
或它的超类型,直到B
。
现在,在modelOpt为Option[Future[Result]]
的情况下,将getOrElse
应用于给定类型为Future[Result]
(或其子类型)的默认值将导致Future[Result]
。
类似于getOrElse
的工作方式,但将Option
保留在原位,方法orElse具有以下签名:
final def orElse[B >: A](alternative: => Option[B]): Option[B]
因此,将orElse
应用于modelOpt如下所示,将返回所需的Option[Future[Result]]
:
modelOpt.orElse(Some(Future.successful(InternalServerError)))
请注意,Future.successful用于提供具有指定结果的已经完成的Future。