2015-08-01 7 views
11

Slicks Unterstützung für HList ist im Allgemeinen eine großartige Sache. Leider kommt es mit einer eigenen Implementierung, die kaum nützliche Operationen bietet. Ich würde daher gerne die formloseHList stattdessen verwenden. Dies soll "trivial" sein, aber ich habe keine Ahnung, wie ich das richtig machen soll. Im Internet habe ich keine Beweise gefunden, dass jemand diese Aufgabe erfüllen konnte.Slick mit formlosem HList verwenden

Ich gehe davon aus, dass es genug ist, ein zu implementieren ProvenShape (wie in der Werbung here), aber da ich nicht das Konzept der Slicks(Proven)Shape s zu verstehen, ich habe es nicht geschafft das umzusetzen.

Ich bin im Grunde diese

class Users(tag: Tag) 
extends Table[Long :: String :: HNil](tag, "users") 
{ 
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc) 

    def email = column[String]("email") 

    override def * = (id, email) <>[TableElementType, (Long, String)](
     _.productElements, 
     hlist => Some(hlist.tupled) 
    ) 
} 

bis

class Users(tag: Tag) 
extends Table[Long :: String :: HNil](tag, "users") 
{ 
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc) 

    def email = column[String]("email") 

    override def * = id :: email :: HNil 
} 
+1

keine Antwort, aber dieser Thread sieht relevant aus: https://github.com/slick/slick/issues/519 –

Antwort

8

zu kochen Ziel Sie treffen den Nagel auf den Kopf - wenn Sie Shapes für HLists produzieren kann, den Rest von Maschinen des Slick wird Schalten Sie den Gang ein, um die ProvenShape zu erzeugen, die Sie für die Standardprojektion benötigen.

Hier ist eine nackte Knochen-Implementierung, die Sie Tables von HLists erstellen können:

import scala.annotation.tailrec 
import scala.reflect.ClassTag 
import shapeless.{ HList, ::, HNil } 
import slick.lifted.{ Shape, ShapeLevel, MappedProductShape } 

final class HListShape[L <: ShapeLevel, M <: HList, U <: HList : ClassTag, P <: HList] 
    (val shapes: Seq[Shape[_, _, _, _]]) extends MappedProductShape[L, HList, M, U, P] { 

    def buildValue(elems: IndexedSeq[Any]) = 
    elems.foldRight(HNil: HList)(_ :: _) 

    def copy(shapes: Seq[Shape[_ <: ShapeLevel, _, _, _]]) = 
    new HListShape(shapes) 

    def classTag: ClassTag[U] = implicitly 

    def runtimeList(value: HList): List[Any] = { 
    @tailrec def loop(value: HList, acc: List[Any] = Nil): List[Any] = value match { 
     case HNil  => acc 
     case hd :: tl => loop(tl, hd :: acc) 
    } 

    loop(value).reverse 
    } 

    override def getIterator(value: HList): Iterator[Any] = 
    runtimeList(value).iterator 

    def getElement(value: HList, idx: Int): Any = 
    runtimeList(value)(idx) 
} 

object HListShape { 
    implicit def hnilShape[L <: ShapeLevel]: HListShape[L, HNil, HNil, HNil] = 
    new HListShape[L, HNil, HNil, HNil](Nil) 

    implicit def hconsShape[L <: ShapeLevel, M1, M2 <: HList, U1, U2 <: HList, P1, P2 <: HList] 
     (implicit s1: Shape[_ <: ShapeLevel, M1, U1, P1], s2: HListShape[_ <: ShapeLevel, M2, U2, P2]): 
     HListShape[L, M1 :: M2, U1 :: U2, P1 :: P2] = 
    new HListShape[L, M1 :: M2, U1 :: U2, P1 :: P2](s1 +: s2.shapes) 
} 

ich auf Github here eine Implementierung gesetzt haben. Im Prinzip denke ich Generic könnte in den Kampf gebracht werden, um Fallklassen ohne die Notwendigkeit <> abzubilden.

+0

Du hättest das Repo "shapefull" nennen sollen;) – nafg

+0

Ack! Was für eine verpasste Gelegenheit. Scheint so offensichtlich in Hind-Sicht :) –