Класс случая Scala, обогащенный абстрактным компонентом (Cake Pattern)

Мы используем шаблон торта для абстрагирования компонентов (DB, Mock) с аннотацией собственного типа, которые вводятся при вызове верхнего уровня.

В одном случае класс мы хотим быть в состоянии улучшить его поведение, расширяя общую черту. Но как это сделать, если мы хотим, чтобы этот case-класс вызывал абстрактный компонент? Рефакторинг класса case как абстрактного приведет к удалению всей реализации apply, unapply, copy ... Вещи, которые нам нужны для сопоставления базы данных и модели (например, с помощью Slick).

Вот пример, представляющий растения в некоторых блоках как ресурсы, принадлежащие учетной записи:

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)
    }
  }
}

Любая идея о том, как это сделать без переопределения всех шаблонов класса дела? Добавление getAccount в сопутствующий объект Resource с сопоставлением с шаблоном case не решит проблему

1 ответ

Решение

Мы решили реализовать ResourceService, который в соответствии с типом ресурса возвращает учетную запись, к которой принадлежит ресурс.

Вот компонент черты:

trait ResourceServiceComponent {

  val resourceService: ResourceService

  trait ResourceService {
    def getAccount(resource: Resource): Future[Account] = {
      resource match {
        case plant: Plant => blockDB.getAccount(plant.blockId)
        case ...
      }
    }
  }
}
Другие вопросы по тегам