我有一个表,其中有多个Option[X]
列。我想对以下事实建模:对于这些列,定义了[[all或缺少了[[all。考虑到将列定义为单独的Option[X]
,该怎么做?
def startDate = column[Option[LocalDate]]("start_date", O.Default(None))
def endDate = column[Option[LocalDate]]("end_date", O.Default(None))
def dateRange: Rep[Option[(LocalDate,LocalDate)]] = ??? // How to make something like this?
Int
而不是LocalDate
为例,我们可以从要使用的案例类开始:case class Row(
name : String,
range : Option[(Int, Int)],
id : Long = 0L
)
注意,range
字段是一个单一值(元组),但是在数据库中,我们可以将其表示为称为start
和end
的两列:
class RowTable(tag: Tag) extends Table[Row](tag, "row") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def start = column[Option[Int]]("start")
def end = column[Option[Int]]("end")
def range = (start, end) <> (into_range, from_range)
def * = (name, range, id).mapTo[Row]
}
*
到Row
的投影是从另一个我称为range
的映射中构建的。
range
映射在两列start
和end
上。我们提供给<>
的两个函数:一个函数将一对选项转换成我们想要的类型(元组的选项);其他功能则相反。这些功能反映了标准库功能tupled
和unappy
(unapply
是extractor)。我们可以根据需要编写这些功能,并且已经通过模式匹配将它们编写出来:
def into_range(pair: (Option[Int], Option[Int])): Option[(Int, Int)] = pair match { case (Some(x), Some(y)) => Some((x, y)) case _ => None } def from_range(r: Option[(Int, Int)]): Option[(Option[Int], Option[Int])] = r match { case Some((x, y)) => Some((Some(x), Some(y))) case _ => Some((None, None)) }
总而言之,在此示例中,您的dateRange
等效于range
映射,但是与其直接调用它,我们不将其包含在默认投影*
中。