播放框架模板 - 迭代列表问题

时间:2013-09-10 11:27:18

标签: scala templates playframework-2.0 slick

我遇到了迭代传递给Play框架模板的List的问题。我本质上有一个从多对多关联中获取的查询,我想要多次呈现父键和关联键。

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

使用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

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

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

2 个答案:

答案 0 :(得分: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]中传递给您可以迭代的视图,这也会更容易。

希望这有帮助。

答案 1 :(得分:0)

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

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

@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

当然,有一种更易读的方法可以做到这一点吗?