(并非如此)Slick 3.1 中的高级映射投影
(Not so) advanced mapped projection in Slick 3.1
我正在研发是否应该为新应用程序使用 Scala 2.11/Play 2.4/Slick 3.1 堆栈。几年前我做过一些 Scala 编程,并将其作为我最喜欢的小型个人项目语言,但高级概念对我来说仍然是个谜。
在阅读了 Matt Handler 的 this 博客 post 之后,我想在我的 PoC 应用程序中复制此行为,但我 运行 遇到了一些问题。
case class BaseModel[A] (id: Long, model: A)
object BaseModel {
import scala.language.implicitConversions
implicit def toModel[A](modelWithId: BaseModel[A]): A = modelWithId.model
}
case class Ingredient(name: String, description: String)
class IngredientsTable(tag: Tag) extends Table[BaseModel[Ingredient]](tag, "ingredients") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def description = column[String]("description")
def * = (id, name, description) <> ??? // ((BaseModel[Ingredient].apply _).tupled, BaseModel[Ingredient].unapply)
}
我的问题是我应该放置什么而不是 ???
因为注释掉 pard 出于明显的原因不起作用?我知道我需要在那里创建一个自定义的 Slick 形状,以便它 boxes/unboxes 包含模型 val 但我应该怎么做(Slick 文档在这件事上没有太大帮助)?
我尝试基于 this answer 做类似的事情,但它给了我编译错误,因为我从早期的 Slick 版本中获取了这个,显然我不明白这里发生了什么。
def * = (id, name, description) <> (
(id, name, description) => BaseModel[Ingredient](id, Ingredient(name, description)),
(f: BaseModel[Ingredient]) => Some((f.id, f.name, f.description))
)
希望我正在寻找更自动化的东西(重写元组,在 BaseModel 中不应用?)但是任何有用的东西和任何帮助都非常感谢。如果指向正确的位置,甚至是 RTFM。
编辑: JimN 提出了一个可行的答案,但在创建每个此类映射时需要大量样板文件。您能否提出一个可以最大限度地减少样板文件数量的答案?
这是添加到 IngredientsTable
的内容:
def toBaseModel(id: Long, name: String, description: String): BaseModel[Ingredient] = {
BaseModel[Ingredient](id, Ingredient(name, description))
}
def fromBaseModel(m: BaseModel[Ingredient]): Option[(Long, String, String)] = {
Some((m.id, m.name, m.description))
}
def * = (id, name, description) <> ((toBaseModel _).tupled, fromBaseModel)
这为我编译:
def * = (id, name, description) <> ((toBaseModelIngredient _).tupled, fromBaseModelIngredient)
...
def toBaseModelIngredient(id: Long, name: String, description: String): BaseModel[Ingredient] = ??? // implement this
def fromBaseModelIngredient(m: BaseModel[Ingredient]): Option[(Long, String, String)] = ??? // implement this
我正在研发是否应该为新应用程序使用 Scala 2.11/Play 2.4/Slick 3.1 堆栈。几年前我做过一些 Scala 编程,并将其作为我最喜欢的小型个人项目语言,但高级概念对我来说仍然是个谜。
在阅读了 Matt Handler 的 this 博客 post 之后,我想在我的 PoC 应用程序中复制此行为,但我 运行 遇到了一些问题。
case class BaseModel[A] (id: Long, model: A)
object BaseModel {
import scala.language.implicitConversions
implicit def toModel[A](modelWithId: BaseModel[A]): A = modelWithId.model
}
case class Ingredient(name: String, description: String)
class IngredientsTable(tag: Tag) extends Table[BaseModel[Ingredient]](tag, "ingredients") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def description = column[String]("description")
def * = (id, name, description) <> ??? // ((BaseModel[Ingredient].apply _).tupled, BaseModel[Ingredient].unapply)
}
我的问题是我应该放置什么而不是 ???
因为注释掉 pard 出于明显的原因不起作用?我知道我需要在那里创建一个自定义的 Slick 形状,以便它 boxes/unboxes 包含模型 val 但我应该怎么做(Slick 文档在这件事上没有太大帮助)?
我尝试基于 this answer 做类似的事情,但它给了我编译错误,因为我从早期的 Slick 版本中获取了这个,显然我不明白这里发生了什么。
def * = (id, name, description) <> (
(id, name, description) => BaseModel[Ingredient](id, Ingredient(name, description)),
(f: BaseModel[Ingredient]) => Some((f.id, f.name, f.description))
)
希望我正在寻找更自动化的东西(重写元组,在 BaseModel 中不应用?)但是任何有用的东西和任何帮助都非常感谢。如果指向正确的位置,甚至是 RTFM。
编辑: JimN 提出了一个可行的答案,但在创建每个此类映射时需要大量样板文件。您能否提出一个可以最大限度地减少样板文件数量的答案?
这是添加到 IngredientsTable
的内容:
def toBaseModel(id: Long, name: String, description: String): BaseModel[Ingredient] = {
BaseModel[Ingredient](id, Ingredient(name, description))
}
def fromBaseModel(m: BaseModel[Ingredient]): Option[(Long, String, String)] = {
Some((m.id, m.name, m.description))
}
def * = (id, name, description) <> ((toBaseModel _).tupled, fromBaseModel)
这为我编译:
def * = (id, name, description) <> ((toBaseModelIngredient _).tupled, fromBaseModelIngredient)
...
def toBaseModelIngredient(id: Long, name: String, description: String): BaseModel[Ingredient] = ??? // implement this
def fromBaseModelIngredient(m: BaseModel[Ingredient]): Option[(Long, String, String)] = ??? // implement this