Подтвердить что ты не робот

Как я могу составлять запросы в ScalaQuery, чтобы создавать повторяющиеся черты?

У меня возникли проблемы с составлением разных компонентов запроса в одном запросе. Моя цель - создать набор признаков (например, SoftDeletable, HasName, SortedByName, WithTimestamps), которые я могу просто подключить к объектам Table, чтобы добавить это поведение.

Идеал выглядел бы так:

abstract class BaseModel[Tuple <: Product,CaseClass](tableName: String)
     extends Table[Tuple](tableName) {
  def id = column[Int]("id", O.AutoInc, O.PrimaryKey)

  def mapped: MappedProjection[CaseClass, TupleClass]

  def allQuery = this.map(_.mapped)
  final def all = database.withSession { implicit session: Session => 
    allQuery.list() 
  }

  ...
}

trait SoftDeletable[Tuple  <: Product, CaseClass]
    extends BaseModel[Tuple,CaseClass] {
  def isActive = column[String]("is_active")

  def * = super.* ~ isActive
  def allQuery = /* here, I'd like to compose super.allQuery 
                    with a filter that returns rows where isActive is true */
}

trait HasName[Tuple <: Product] extends Table[Tuple] {
  def name = column[String]("name")

  def * = super.* ~ name
}

trait SortedByName[Tuple <: Product] extends HasName[Tuple {
  override def allQuery = super.allQuery /* compose somehow 
                                             with (_ <- Query orderBy name */
}

Могу ли я делать такие вещи с помощью ScalaQuery? Основными точками крепления являются:

  • Как очистить фильтры в SoftDeletable.allQuery и сортировку в SortedByName.allQuery с помощью BaseModel.allQuery?

  • Добавляя столбцы в реализации подкласса метода *, параметр типа tuple до Table не совпадает с последним - существует ли способ, чтобы эти признаки добавляли новые типы к кортежу столбцов в конечной конкретный класс? (Я не ожидаю, что это произойдет, но было бы неплохо, если бы что-то мне не хватило).

  • Мне нужно повторить длинную декларацию в каждом признаке, которая становится очень громоздкой, если таблица имеет пять или шесть столбцов. Есть ли что-то, что я могу сделать с членами типа, чтобы избежать необходимости делать такие вещи, как:

    case class Foo
    
    class Foos[(Int,Int,Boolean,String), Foo] extends 
      Table[(Int,Int,Boolean,String)] with 
      SoftDeletable[(Int,Int,Boolean,String), Foo] with 
      SortedByName[(Int,Int,Boolean,String), Foo] with 
      HasName[(Int,Int,Boolean,String)] {
    }
    

Можно ли избежать этого повторения? Основываясь на предположении от jesnor на IRC, я смог избежать некоторых из них следующим образом:

abstract class SoftDeletableBaseModel[TupleClass <: Product, CaseClass](tableName: String)
        extends BaseModel[TupleClass, CaseClass](tableName)
        with SoftDeletable[TupleClass,CaseClass]

Другими словами, объединяя определенные черты вместе, мне не нужно повторять всю декларацию кортежа; конечно, недостаток заключается в том, что легкое смешивание различных признаков больше невозможно - мне нужно создать множество определенных подклассов, чтобы избежать повторения. Есть ли другой способ?

Обновление. Поэтому я понял, что мне не нужно использовать отдельные параметры типа CaseClass и TupleClass. Поскольку классы case реализуют Product*, вы можете просто передать имя класса case в таблицу, что решает проблему в 3:

trait SoftDeletable[CaseClass] extends BaseModel[CaseClass] { ... }

class Models extends BaseModel[Model]("models") with SoftDeletable[Model] { ... }
4b9b3361

Ответ 1

Если ваша проблема только добавляет сортировку, это не вопрос flatMap?

def sortBy[T,U,C](q: Query[T,U], col: NamedColumn[C]) = q.flatMap(_ => Query orderBy col)