0

我在迭代传递给 Play 框架模板的列表时遇到问题。我基本上有一个从多对多关联中获取的查询,我想渲染一次父键和多次关联键。

以下是我正在使用的实际代码:

使用 Slick、Scala 和 Play 2.0,我有以下表模式:

object Recipes extends Table[(Long, String, String)]("RECIPES") {
  def id = column[Long]("REC_ID", O.PrimaryKey, O.AutoInc)
  def cuisine = column[String]("CUISINE")
  def instructions = column[String]("INSTRUCTIONS")
  def * = id ~ cuisine ~ instructions
}

object Ingredients extends Table[(Long, String, String)]("INGREDIENTS") {
  def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
  def brand = column[String]("BRAND")
  def name = column[String]("NAME")
  def * = id ~ brand ~ name
}

object RecipeIngredient extends Table[(Long, Long, Long, Int, String)]("REC_ING") {
  def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)

  def recID = column[Long]("REC_ID")
  def ingID = column[Long]("ING_ID")
  def quantity = column[Int]("QUANTITY")
  def units = column[String]("UNITS")
  def * = id ~ recID ~ ingID ~ quantity ~ units
  def recipe = foreignKey("REC_FK", recID, Recipes)(_.id)
  def ingredient = foreignKey("ING_FK", ingID, Ingredients)(_.id)
}

我正在使用 Slick 在控制器中生成以下查询,并传递q.list给视图。这个想法是传递和渲染 ID 为 1 的配方及其所有相关成分:

val recID = 1.longValue() // Just a test to get the Recipe with ID === 1
val q = for {
    r <- Recipes if r.id === recID
    ri <- RecipeIngredient if ri.recID === recID
i <-Ingredients if i.id === ri.ingID
} yield (r.id, r.cuisine, r.instructions, ri.quantity, ri.units, i.brand, i.name)

我的看法如下:

@(message: String, result: List[(Long, String, String, Int, String, String, String)])

@main("Site name") {

    @for((id, cuisine,instructions, quantity, units, brand, name) <- result) {

    <h2>--Recipe--</h2>
      RecID: @id <br>
      Cuisine: @cuisine <br>
      Instructions: @instructions <br>

      <h2>--Ingredients--</h2>
      Ingredient: @quantity @units of @brand @name<br>
  }


}

这一切都很好,但我得到如下输出:

--Recipe--
RecID: 1 
Cuisine: Chinese 
Instructions: Instructions here..

--Ingredients--
Ingredient: 3 cloves of Generic Ginger

--Recipe--
RecID: 1 
Cuisine: Chinese 
Instructions: Instructions here..

--Ingredients--
Ingredient: 3 slices of Generic Cucumber

如您所见,配方本身重复了两次。我最终想要的是打印一次的食谱,以及在此之后交互和显示的相关成分列表(可能有多种成分)。

关于如何实现这一目标的任何想法?

4

2 回答 2

1

就最佳实践/更优雅的方式而言,您应该考虑创建一个食谱案例类来保存您的食谱的所有信息;这将使您的代码更简洁,更易于使用:

case class Recipe(val id: Long, val cuisine: String, val instructions: String, val quantity: Int, val units: String, val brand: String, val name: String)

注意:当我访问视图中的字段时,所有字段都明确标记为 val,以便于使用。然后,您可以将查询转换为对象(来自scala slick query return value

def getRecipe(recID: Long): Option[Recipe] = {
  val q = for {
    r <- Recipes if r.id === recID
    ri <- RecipeIngredient if ri.recID === recID
    i <-Ingredients if i.id === ri.ingID
  } yield (r.id, r.cuisine, r.instructions, ri.quantity, ri.units, i.brand, i.name)
  q.firstOption map { case (id, cui, ins, qua, uni, bra, na) => Recipe(id, cui, ins, qua, uni, bra, na) }
}

然后,您可以将其传递给您的视图:

@(message: String, recipe: Recipe)

@main("Site name") {

@recipe match {
  case r:Some(Recipe) => {
    <h2>--Recipe--</h2>
    RecID: @r.id <br>
    Cuisine: @r.cuisine <br>
    Instructions: @r.instructions <br>

    <h2>--Ingredients--</h2>
    Ingredient: @r.quantity @r.units of @r.brand @r.name<br>
  }
  case None => {
    <h2>No Recipe</h2>
  }
}
}

您可以做一些不同的事情,例如为 Recipe 案例类创建一个伴随对象类,摆脱传递给您的视图的 Option[Recipe] 等。如果您想选择多个食谱并传递,这也将使您更容易将它们放在 List[Recipe] 中的视图中,然后您可以对其进行迭代。

希望这可以帮助。

于 2013-09-11T15:39:41.913 回答
0

我想出了一种方法来解决这个问题,虽然它看起来非常h​​acky,所以我仍然热衷于理解最佳实践,优雅的方式来做到这一点。

我的解决方案 - 通过将视图更改为:

@main("Site name") {

// This is a hacky way to just show the Recipe components once
@for((item, index) <- result.zipWithIndex) {
@if(index == 0) {

    <h2>---Recipe---</h2>
      RecID: @item._1 <br>
      Cuisine: @item._2<br>
      Instructions: @item._3 <br>

        <h2>---Ingredients---</h2>

    }
}

// And now we list all ingredients..
    @for((id, cuisine,instructions, quantity, units, brand, name) <- result) {
    <!--<h2>Recipe</h2>
      RecID: @id <br>
      Cuisine: @cuisine <br>
      Instructions: @instructions <br>-->
      Ingredient: @quantity @units of @brand @name<br>
  }


}

..我得到了我想要的输出:

---Recipe---
RecID: 1 
Cuisine: Chinese
Instructions: Instructions here

---Ingredients---
Ingredient: 3 cloves of Generic Ginger
Ingredient: 3 slices of Generic Cucumber

当然有一种更易读的方法来做到这一点?

于 2013-09-10T12:02:44.250 回答