在 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 参数?