我在遍历传递到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
如您所见,Recipe本身重复了两次。我最终想要的是将食谱打印一次,然后插入相关的成分列表并在其后显示(可能有多种成分)。
关于如何实现这一目标的任何想法?
就最佳实践/一种更优雅的方式而言,您应该考虑创建一个食谱案例类来保存食谱的所有信息。这将使您的代码更简洁,更易于使用:
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查询的返回值)
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 Case类创建一个伴随对象类,摆脱传递给视图的Option [Recipe],等等。如果您要选择多个配方并传递,这也将变得更加容易。将它们放在一个List [Recipe]中,然后可以进行迭代。
希望这可以帮助。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句