We use the cake pattern to abstract Components (DB, Mock) with self-type annotation, that are Injected at the top level call.
In one case class we want to be able to enrich it's behavior by extending common trait. But how to do it if we want this case class to call an abstract component? Refactoring the case class as abstract will remove all the implementation of apply, unapply, copy ... Things that we need to do the mapping between database and model (for example using Slick).
Here is an exemple representing Plants into some Blocks as Resources owned by an Account:
trait Resource {
def getAccount: Future[Account]
}
case class Account(id: Int)
case class Block(id: Int, name:String, accountId: Int) extends Resource
case class Plant(id: Int, name: String, blockId: Int) extends Resource {
this: PlantDBComponent =>
override def getAccount: Future[Account] = plantDB.getAccount(this)
}
trait PlantDBComponent {
def plantDB: PlantDB
trait PlantDB {
def getAccount(plant: Plant): Future[Account]
}
}
trait SlickPlantDBComponent {
def blockDB = SlickPlantDB()
trait SlickPlantDB extends PlantDB {
def getAccount(block: Block): Future[Account] = {
val q = for {
block <- BlockTable if block.id === plant.blockId
account <- AccountTable if account.id === block.accountId
} yield account
db.run(q.result.head)
}
}
}
Any idea on how to do it without reimplementing all the case class boilerplate? Adding getAccount in a Resource companion object with case class pattern matching will not solve the problem
Account
aResource
? – pamu