0

我正在尝试执行几个相关的 Slick/DB 调用,然后在旋转模板中显示结果数据。

def show(slug: String) = Action.async { implicit rs =>

    for {

      f <- fooDAO.findBySlug(slug)  // f is of type Option[foo]
      fid <- f.flatMap(a => a.id.map(b => b)) // fid is of type Long
      b <- barDAO.findByFooId(fid) // b is of type Seq[bar] 

    } yield {

        f.map {
          case Some(f) => Ok(views.html.foobar(f, b))
          case _ => NotFound
        }

      }
  }

我首先需要获取“ID”,然后才能查询其他相关数据。编译器现在产生此错误:

play.sbt.PlayExceptions$CompilationException: Compilation error[type mismatch;
 found   : scala.concurrent.Future[Option[play.api.mvc.Result]]
 required: Option[?]]

任何帮助将不胜感激。

4

2 回答 2

1

您的代码中有一个根本缺陷,因为您混合了相同的理解 anOption和 aSeq

一个 for-comprehension 预计将在相同的“容器”类型上工作,这将是yield

例如,如果你结合几个Options 你得到一个Option,如果你结合Seqs 你得到一个Seq

在这种情况下,您可以通过将Option(foo) 转换为 a 来解决该问题(Seq如果 foo 是则它将为空,None如果不是则具有 1 个元素)。

最终结果将是

val results: Seq[(Foo, Bar)] =
  for {
    f <- fooDAO.findBySlug(slug).toSeq  // f is of type Seq[Foo]
    b <- barDAO.findByFooId(f.id) // b is of type Seq[Bar] 
  } yield (f, b)

但我想这不是你需要的。我想您想获取Bar与检索到的所有关联的 s Foo(如果有),并将其与您的模板一起呈现。如果 没有Fooslug你想要一个NotFound

我们可以这样做

def show(slug: String) = Action.async { implicit rs =>

  val f = fooDAO.findBySlug(slug)  // f is of type Option[Foo]

  f.fold(
    NotFound,
    foo => Ok(views.html.foobar(foo, barDAO.findByFooId(foo.id))
  )

}

您可以通过定义支持方法使其更明确

def show(slug: String) = Action.async { implicit rs =>

  def barsOf(f: Foo): Seq[Bar] = barDAO.findByFooId(f.id)

  val f = fooDAO.findBySlug(slug)  // f is of type Option[Foo]

  f.fold(
    NotFound,
    foo => Ok(views.html.foobar(foo, barsOf(foo))
  )

}
于 2015-06-03T08:59:52.087 回答
0

理解你在这里想要实现的目标有点棘手,但如果整个事情都是基于findbySlug返回的 aFuture[Option[Foo]]并且最终结果是 a NotFoundif that Optionis a None,那么你yield可能应该是:

   ...
 } yield {
  f.fold(NotFound)(foo => Ok(views.html.foobar(foo, b)))
}

Option[T]是一种用于数据检索和控制流的奇妙类型,但对其进行模式匹配几乎从来都不是正确的方法。对任务的使用fold感觉非常简洁。

于 2015-06-03T03:34:23.480 回答