Допустим, у меня есть класс, называемый случая Blarg
, состоящий из свойств с примитивными типами:Как превратить Slick 2.1.0 MappedProjection поэтому все Столбики Опция
case class Blarg(
x: String,
y: Int
)
Blarg
s используется в различных классах, иногда как Option[Blarg]
, иногда как List[Blarg]
, и эти классы сохраняются. Мы также имеем случай класс под названием OptionalComplexThing
, содержащее свойство типа Option[Blarg]
:
case class OptionalComplexThing(
one: String,
maybeInt: Option[Int],
maybeBlarg: Option[Blarg],
id: Option[Long] = None
)
Проблема заключается в том, как создать по умолчанию MappedProjection
, содержащего соответствующую суб-проекцию. Обратите внимание на приведенный ниже blarg
MappedProjection
. Я хочу иметь возможность преобразовывать blarg
MappedProjection
, поэтому все его Column
s - Option
s. Я не хочу жестко кодировать этот пример - должен быть общий способ сделать это с помощью комбинаторов.
class _OptionalComplexThings(tag: Tag) extends Table[OptionalComplexThing](tag, "optional_complex_thing") {
def one = column[String]("one")
def maybeInt = column[Option[Int]]("maybe_int") // specifying O.Nullable makes no difference
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
// Blarg fields need to have their lifted types remapped according to MappedProjection usage.
// Notice OptionalComplexThing's maybeBlarg property is an Option[Blarg].
def x = column[String]("x") // want to map to column[Option[String]]("x")
def y = column[Int]("y") // want to map to column[Option[String]]("y")
def blarg = (x, y) <> (Blarg.tupled, Blarg.unapply)
def * = (one, maybeInt, Option(blarg), id) <> (OptionalComplexThing.tupled, OptionalComplexThing.unapply)
/* Error:(23, 46) No matching Shape found.
Slick does not know how to map the given types.
Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported type in a Query (e.g. scala List).
Required level: scala.slick.lifted.FlatShapeLevel
Source type: (scala.slick.lifted.Column[String], scala.slick.lifted.Column[Option[Int]], Option[scala.slick.lifted.MappedProjection[Blarg,(String, Int)]], scala.slick.lifted.Column[Option[Long]])
Unpacked type: (String, Option[Int], Option[Blarg], Option[Long])
Packed type: Any
def * = (one, maybeInt, Option(blarg), id) <> (OptionalComplexThing.tupled, OptionalComplexThing.unapply)
^*/
}
Here is a a GitHub project это демонстрирует вопрос.
Это ручной подход, который я бы хотел избежать. Проблема с этим подходом заключается в том, что кто-то должен его поддерживать, и по мере перехода проектов в будущее люди уходят и свойства класса case меняются. Вместо этого я хотел бы использовать комбинаторы. Как можно добиться чего-то подобного без ручной работы Blarg.fromOptions и customUnapply? –