在 ActionBuilder 中从 Future 中提取选项

Posted

技术标签:

【中文标题】在 ActionBuilder 中从 Future 中提取选项【英文标题】:Extract Option from Future in ActionBuilder 【发布时间】:2021-04-24 15:49:49 【问题描述】:

我正在基于此Scala Play Authentication 示例实施身份验证。

因此我使用以下ActionBuilder 来构建UserAction

UserAction.scala

class UserRequest[A](val user: Option[Admin], request: Request[A]) extends WrappedRequest[A](request)

class UserAction @Inject()(adminService: AdminService, parser: BodyParsers.Default)(implicit val executionContext: ExecutionContext)
  extends ActionBuilder[UserRequest, AnyContent]
    with ActionTransformer[Request, UserRequest] 

  def transform[A](request: Request[A]) = Future.successful 

    val sessionTokenOpt = request.session.get("sessionToken")

    val user = sessionTokenOpt
      .flatMap(token => Sessions.getSession(token))
      .filter(_.expiration.isAfter(LocalDateTime.now(ZoneOffset.UTC)))
      .map(_.email)
       // Signature: getAdminByEmail(email: String): Future[Option[Admin]]
      .flatMap(adminService.getAdminByEmail) // <- Extract Future here

    // The user has to be Option[Admin] but is Future[Option[Admin]]
    // because of adminService.getAdminByEmail
    new UserRequest(user, request)
  

由于 example implementation in line 25 没有返回 Future 因为没有包含数据库设置,所以我收到以下错误:

type mismatch;
 found   : scala.concurrent.Future[Option[models.Tables.Admin]]
 required: Option[?]

因为我是 scala 的新手,所以我现在不知道如何提取 Future。如何处理 Future 结果以确保我们返回Option[Admin]

【问题讨论】:

我为你自己做这件事感到高兴。这通常更有利。下次请创建minimal reproducible example。例如,当我们不知道adminService.getAdminByEmail 的签名是什么时,真的很难回答这样的问题。 签名在代码中作为注释可用。但我下次尝试更明确。谢谢 【参考方案1】:

我自己修复了它。我只是将电子邮件和获取分成两个不同的部分,并将@​​987654321@ 移动到email match 内。

class UserAction @Inject()(adminService: AdminService, val parser: BodyParsers.Default)(implicit val executionContext: ExecutionContext)
  extends ActionBuilder[UserRequest, AnyContent]
    with ActionTransformer[Request, UserRequest] 

  def transform[A](request: Request[A]) : Future[UserRequest[A]] = 
    val sessionTokenOpt = request.session.get("sessionToken")

    val email = sessionTokenOpt
      .flatMap(token => Sessions.getSession(token))
      .filter(_.expiration.isAfter(LocalDateTime.now(ZoneOffset.UTC)))
      .map(_.email)

    email match 
      case Some(value) =>
        adminService.getAdminByEmail(value).map(a => new UserRequest(a, request))
      case None =>
        Future  new UserRequest(None, request) 
    
  

【讨论】:

以上是关于在 ActionBuilder 中从 Future 中提取选项的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Play 2.5 框架中使用授权 ActionBuilder 保护静态文件

如何模拟 ActionBuilder 的 BodyParser.Default 参数?

在 Flutter 中从 API 获取数据

如何在 Flutter 中从 SQLite 获取数据?

在 Flutter 中从 Firebase 检索用户电子邮件

在构造函数颤动中从 API 更新值