Created
October 16, 2015 08:10
-
-
Save blast-hardcheese/779bb962cda1a27b8ad8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import shapeless._ | |
import shapeless.labelled.KeyTag | |
import shapeless.record._ | |
import shapeless.ops.hlist.ToList | |
import shapeless.ops.record.{ Keys, Values } | |
import shapeless.syntax.singleton._ | |
import utils.ExtendedPostgresDriver.simple._ | |
object slickless { | |
import scala.annotation.tailrec | |
import scala.reflect.ClassTag | |
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) | |
} | |
trait HListShapeImplicits { | |
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) | |
} | |
object SlicklessImplicits extends HListShapeImplicits | |
} | |
import slickless.SlicklessImplicits._ | |
object Dynamic { | |
type BookTuple = (Long, String, String, Double) | |
type BookType = ::[Long, ::[String, ::[String, ::[Double, HNil]]]] | |
val _bookBuilder = implicitly[Generic.Aux[BookTuple, BookType]] | |
def apply(id: Long, author: String, title: String, price: Double): BookType = _bookBuilder.to(id, author, title, price) | |
def unapply(book: BookType): Option[BookTuple] = Some(_bookBuilder.from(book)) | |
} | |
object Explicit { | |
type BookTuple = (Long, String, String, Double) | |
type BookType = Record.`"id" -> Long, "author" -> String, "title" -> String, "price" -> Double`.T | |
def apply(id: Long, author: String, title: String, price: Double): BookType = { | |
("id" ->> id) :: | |
("author" ->> author) :: | |
("title" ->> title) :: | |
("price" ->> price) :: | |
HNil | |
} | |
val tupled: BookTuple => BookType = (apply _).tupled | |
def unapply(book: BookType): Option[BookTuple] = { | |
val id :: author :: title :: price :: HNil = book | |
Some((id, author, title, price)) | |
} | |
class Books(tag: Tag) extends Table[Long :: String :: String :: Double :: HNil](tag, "book") { | |
def id = column[Long ]("id", O.PrimaryKey, O.AutoInc) | |
def author = column[String]("author", O.NotNull) | |
def title = column[String]("title", O.NotNull) | |
def price = column[Double]("price", O.NotNull) | |
def * = ("id" ->> id) :: ("author" ->> author) :: ("title" ->> title) :: ("price" ->> price) :: HNil | |
} | |
val books = TableQuery[Books] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scala> val fromdb = DB.withSession { implicit s => Explicit.books.filter(_.id === 1L).run } | |
fromdb: Seq[Explicit.Books#TableElementType] = Vector(1 :: Devon Stewart :: Doing stuff :: 13.37 :: HNil) | |
scala> fromdb.head | |
res2: Explicit.Books#TableElementType = 1 :: Devon Stewart :: Doing stuff :: 13.37 :: HNil | |
scala> fromdb.head("author") | |
<console>:47: error: No field String("author") in record shapeless.::[Long,shapeless.::[String,shapeless.::[String,shapeless.::[Double,shapeless.HNil]]]] | |
fromdb.head("author") | |
^ | |
scala> val a = fromdb.head | |
a: Explicit.Books#TableElementType = 1 :: Devon Stewart :: Doing stuff :: 13.37 :: HNil | |
scala> a: Explicit.BookType | |
<console>:48: error: type mismatch; | |
found : Explicit.Books#TableElementType | |
(which expands to) shapeless.::[Long,shapeless.::[String,shapeless.::[String,shapeless.::[Double,shapeless.HNil]]]] | |
required: Explicit.BookType | |
(which expands to) shapeless.::[Long with shapeless.labelled.KeyTag[String("id"),Long],shapeless.::[String with shapeless.labelled.KeyTag[String("author"),String],shapeless.::[String with shapeless.labelled.KeyTag[String("title"),String],shapeless.::[Double with shapeless.labelled.KeyTag[String("price"),Double],shapeless.HNil]]]] | |
a: Explicit.BookType | |
^ | |
scala> a.asInstanceOf[Explicit.BookType] | |
res5: Explicit.BookType = 1 :: Devon Stewart :: Doing stuff :: 13.37 :: HNil | |
scala> res5("author") | |
res6: String = Devon Stewart | |
scala> res5("bogus") | |
<console>:49: error: No field String("bogus") in record shapeless.::[Long with shapeless.labelled.KeyTag[String("id"),Long],shapeless.::[String with shapeless.labelled.KeyTag[String("author"),String],shapeless.::[String with shapeless.labelled.KeyTag[String("title"),String],shapeless.::[Double with shapeless.labelled.KeyTag[String("price"),Double],shapeless.HNil]]]] | |
res5("bogus") | |
^ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment