Как я могу получить это для понимания, чтобы вернуться? - PullRequest
0 голосов
/ 20 января 2019

Я создаю контроллер, который общается со службой.Контроллер (основанный на библиотеке Play 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, поэтому я думаю, что внешний тип должен быть опцией.Кто-нибудь может показать мне, что происходит?

1 Ответ

0 голосов
/ 20 января 2019

Если вы посмотрите на сигнатуру метода getOrElse в признаке Option[A]:

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 с указанным результатом.

...