2016-05-13 7 views
0

Допустим, у меня есть класс, называемый случая 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, содержащего соответствующую суб-проекцию. Обратите внимание на приведенный ниже blargMappedProjection. Я хочу иметь возможность преобразовывать blargMappedProjection, поэтому все его 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 это демонстрирует вопрос.

ответ

0

Вы можете написать свои собственные версии tupled/методы Исключить:

case object Blarg { 
    def fromOptions(maybeX: Option[String], maybeY: Option[Int]): Option[Blarg] = { 
    (maybeX, maybeY) match { 
     case (Some(x), Some(y)) => Some(Blarg(x, y)) 
     case _ => None 
    } 
    } 

    def customTupled = (fromOptions _).tupled 
    def customUnapply(arg: Option[Blarg]): Option[(Option[String], Option[Int])] = arg.map { blarg => 
    (Some(blarg.x), Some(blarg.y)) 
    } 
} 

class _OptionalComplexThings(tag: Tag) extends Table[OptionalComplexThing](tag, "optional_complex_thing") { 
    def one  = column[String]("one") 
    def maybeInt = column[Option[Int]]("maybe_int") 
    def id  = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc) 
    def maybeX = column[Option[String]]("x") 
    def maybeY = column[Option[Int]]("y") 

    def blarg = (maybeX, maybeY) <> (Blarg.customTupled, Blarg.customUnapply) 
    def * = (one, maybeInt, blarg, id) <> (OptionalComplexThing.tupled, OptionalComplexThing.unapply) 
} 

Это не может быть кратчайшее возможное решение, но должно работать.

+0

Это ручной подход, который я бы хотел избежать. Проблема с этим подходом заключается в том, что кто-то должен его поддерживать, и по мере перехода проектов в будущее люди уходят и свойства класса case меняются. Вместо этого я хотел бы использовать комбинаторы. Как можно добиться чего-то подобного без ручной работы Blarg.fromOptions и customUnapply? –

 Смежные вопросы

  • Нет связанных вопросов^_^