在Slick中将ADT映射到多个列

时间:2015-03-25 14:41:48

标签: scala slick

我正在尝试将ADT(case class es继承自sealed trait)映射为同一个表的多个列,使用Slick,如下所示:

sealed trait OrValue
case class IntValue(value: Int)
case class StringValue(value: String)

case class Thing(id: Int, value: OrValue)

class Things(tag: Tag) extends Table[Thing](tag, "things") {
  def id = column[Int]("id", O.PrimaryKey)
  def intValue = column[Option[Int]]("intValue")
  def stringValue = column[Option[String]]("stringValue")

  def toThing(_id: String, _intValue: Option[Int], _stringValue: Option[String]): Thing = Thing(id, ((_intValue, _stringValue) match {
    case (Some(a), None) => IntValue(a)
    case (None, Some(a)) => StringValue(a)
  }

  def fromThing(t: Thing): (String, Option[Int], Option[String]) = ??? // elided

  def * = (id, intValue, stringValue) <> ((toThing _).tupled, fromThing)
}

这不符合:

[error]  found   : [U]slick.lifted.MappedProjection[Thing,U]
[error]  required: slick.lifted.ProvenShape[Thing]
[error]            ) <> ((toThing _).tupled, fromThing _)

我接近这个错误的方式吗? 代表ADT的惯用方法是什么?

2 个答案:

答案 0 :(得分:0)

问题在于方法toThingfromThing的签名。

看起来应该如此:

sealed trait OrValue
case class IntValue(value: Int)
case class StringValue(value: String)

case class Thing(id: Int, value: OrValue)

class Things(tag: Tag) extends Table[Thing](tag, "things") {
  def id = column[Int]("id", O.PrimaryKey)
  def intValue = column[Option[Int]]("intValue")
  def stringValue = column[Option[String]]("stringValue")

  def toThing(source: (Int, Option[Int], Option[String])): Thing = source match {
    case (id, intValue, stringValue) => ??? //TODO implement
  }
  def fromThing(t: Thing): Option[(Int, Option[Int], Option[String])] = ??? //TODO implement

  def * = (id, intValue, stringValue) <> (toThing _, fromThing _)
}

答案 1 :(得分:-1)

您不应将具有相同名称的映射和案例类命名。例如,将地图类更改为Router.route('/test', { waitOn: function() { console.log("waitOn is running (should see this message once for each subscription"); return [ Meteor.subscribe('item_ownership_pub'), Meteor.subscribe('my_items') ]; }, data: function(){ var query = this.params.query; console.log("query: ", query); return query; }, action: function(){ console.log("this will re-render if url params changed"); this.render(); } })