Reputation: 20090
When using Slick CaseClass shape, I am currently facing a situation where for efficiency reasons of a groupBy clause, I would need three columns to be stored in the relational model, while only two fields exists in my object oriented model ( the third being computed)
case class MyEntry(quantity:Double, time:LocalDateTime){
val weight = time.getHour match {
case x if x>=7 && x<=23 => 0.1
case _ => 0.05
}
}
case class LiftedMyTuple(quantity:Rep[Double],time:Rep[LocalDateTime], weight:Rep[Double])
implicit object MyEntryShape extends CaseClassShape(???,???)
class MyTableRow(tag:Tag) extends Table[MyEntry](tag, "MY_TABLE"){
def quantity = column[Double]("QUANTITY")
def time = column[LocalDateTime]("TIME",O.PrimaryKey)
def weight = column[Double]("WEIGHT")
def * = LiftedMyTuple(quantity,time,weight)
}
How does one write a CaseClassShape for such a usage, where the case class has a computed property which should appear in the relational model?
Upvotes: 0
Views: 542
Reputation: 37461
It looks like the constructor is CaseClassShape(mapLifted: (LiftedTuple) ⇒ LiftedCaseClass, mapPlain: (PlainTuple) ⇒ PlainCaseClass)
We should be able to satisfy that like this:
object myShape extends
CaseClassShape(
LiftedMyTuple.tupled,
{ (quantity, time, ignored) => MyEntry(quantity, time) }
)
If you change your case class to store weight but provide a constructor that computes it, you can get read-from-db behavior on the db->code side and compute behavior on the code->db side.
object MyEntry {
def apply(quantity: Double, time: LocalDateTime) = {
val weight = time.getHour match {
case x if x>=7 && x<=23 => 0.1
case _ => 0.05
}
MyEntry(quantity, time, weight)
}
}
case class MyEntry(quantity: Double, time: LocalDateTime, weight: Double)
object myShape extends CaseClassShape(LiftedMyTuple.tupled, MyShape.apply.tupled)
val example = MyShape(0.0, now) // computes weight
Note that I'm calling MyShape.apply
explicitly instead of MyShape
- because we've created a new apply method the compiler will no longer automatically infer that MyShape
means MyShape.apply
(when it's being passed as a function).
Upvotes: 1