Skip to content

Commit

Permalink
Merge pull request #10 from underscoreio/feature/generic-mapping
Browse files Browse the repository at this point in the history
Add functionality to map case classes using Generic
  • Loading branch information
d6y authored Sep 24, 2016
2 parents 5a94296 + 51613d2 commit f9da95d
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
19 changes: 17 additions & 2 deletions src/main/scala/slickless/HListShape.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package slickless

import scala.annotation.tailrec
import scala.reflect.ClassTag
import shapeless.{ HList, ::, HNil }
import slick.lifted.{ Shape, ShapeLevel, MappedProductShape }
import shapeless.{ HList, ::, HNil, Generic }
import slick.ast.MappedScalaType
import slick.lifted.{ Shape, ShapeLevel, FlatShapeLevel, MappedProductShape, MappedProjection }

final class HListShape[L <: ShapeLevel, M <: HList, U <: HList : ClassTag, P <: HList]
(val shapes: Seq[Shape[_, _, _, _]]) extends MappedProductShape[L, HList, M, U, P] {
Expand Down Expand Up @@ -40,4 +41,18 @@ trait HListShapeImplicits {
(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)

implicit class HListShapeOps[T <: HList](hlist: T) {
def mappedWith[R: ClassTag, U <: HList](gen: Generic.Aux[R, U])
(implicit shape: Shape[_ <: FlatShapeLevel, T, U, _]) =
new MappedProjection[R, U](
shape.toNode(hlist),
MappedScalaType.Mapper(
(gen.to _).asInstanceOf[Any => Any],
(gen.from _).asInstanceOf[Any => Any],
None
),
implicitly[ClassTag[R]]
)
}
}
42 changes: 42 additions & 0 deletions src/test/scala/slickless/GenShapeSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package slickless

import org.scalatest.concurrent.ScalaFutures
import org.scalatest.time.{Millis, Seconds, Span}
import org.scalatest.{FreeSpec, Matchers}
import shapeless.{::, HNil, Generic}
import slick.driver.H2Driver.api._

import scala.concurrent.ExecutionContext.Implicits.global

class GenShapeSpec extends FreeSpec with Matchers with ScalaFutures {
implicit val patience = PatienceConfig(timeout = Span(1, Seconds), interval = Span(250, Millis))

case class Address(id: Long, house: Int, street: String)

class Addresss(tag: Tag) extends Table[Address](tag, "addresses") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def house = column[Int]("house")
def street = column[String]("street")

def * = (id :: house :: street :: HNil).mappedWith(Generic[Address])
}

lazy val addresses = TableQuery[Addresss]

"slick tables with generic mappings" - {
"should support inserts and selects" in {
val db = Database.forConfig("h2")

val address = Address(1L, 29, "Acacia Road")

val action = for {
_ <- addresses.schema.create
_ <- addresses += address
ans <- addresses.result.head
_ <- addresses.schema.drop
} yield ans

whenReady(db.run(action)) { _ should equal(address) }
}
}
}
3 changes: 2 additions & 1 deletion src/test/scala/slickless/HListShapeSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ class HListShapeSpec extends FreeSpec with Matchers with ScalaFutures {

lazy val users = TableQuery[Users]

"slick tables with shapeless mappings" - {
"slick tables with hlist mappings" - {
"should support inserts and selects" in {
val db = Database.forConfig("h2")

val action = for {
_ <- users.schema.create
_ <- users += 1L :: "dave@example.com" :: HNil
ans <- users.result.head
_ <- users.schema.drop
} yield ans

whenReady(db.run(action)) { _ should equal (1L :: "dave@example.com" :: HNil) }
Expand Down

0 comments on commit f9da95d

Please sign in to comment.