Ich habe Probleme beim Erstellen verschiedener Abfragekomponenten in einer einzelnen Abfrage. Mein Ziel ist es, eine Reihe von Eigenschaften (z. B. SoftDeletable, HasName, SortedByName, WithTimestamps) zu erstellen, die ich einfach zu Table-Objekten hinzufügen kann, um dieses Verhalten hinzuzufügen.Wie kann ich Abfragen in ScalaQuery erstellen, um wiederverwendbare Merkmale zu erstellen?
wäre die ideale wie folgt aussehen:
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 */
}
Kann ich diese Art von Dingen mit ScalaQuery tun? Die wichtigsten Knackpunkte sind:
Wie kann ich komponieren sauber die Filter in
SoftDeletable.allQuery
und die Art inSortedByName.allQuery
mitBaseModel.allQuery
?von Spalten in der Unterklasse Implementierungen der
*
Methode hinzufügen, die Tupel-Typ-Parameter aufTable
keine letztere Spiele - gibt es eine Möglichkeit für diese Züge schrittweise auf neue Typen hinzufügen, um die Spalten in der ultimative konkreten Klasse Tupel? (Ich erwarte nicht, dass es da ist, aber es wäre schön, wenn ich etwas verpassen würde).Ich muss die lange Tupel-Deklaration in jedem Merkmal wiederholen, was sehr unhandlich wird, wenn eine Tabelle fünf oder sechs Spalten hat. Gibt es etwas, das ich mit Typ-Mitglieder tun können, um zu vermeiden, Dinge zu tun, wie:
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)] { }
Kann ich alle diese Wiederholungen zu vermeiden? Basierend auf einem Vorschlag von jesnor im IRC konnte ich einige dies zu vermeiden, wie so:
abstract class SoftDeletableBaseModel[TupleClass <: Product, CaseClass](tableName: String)
extends BaseModel[TupleClass, CaseClass](tableName)
with SoftDeletable[TupleClass,CaseClass]
Mit anderen Worten, durch bestimmte Merkmale zusammen kombiniert, brauche ich nicht die gesamte Tupel Erklärung zu wiederholen; Der Nachteil ist natürlich, dass ein leichtes Einmischen verschiedener Eigenschaften nicht mehr möglich ist - ich muss viele spezifische Unterklassen erstellen, um diese Wiederholung zu vermeiden. Gibt es eine andere Art und Weise?
Update: So erkannte ich, dass ich nicht separate CaseClass und TupleClass-Typ-Parameter verwenden müssen. Da Fallklassen Product*
implementieren, können Sie die Fall Klassennamen in der Tabelle nur passieren, die das Problem in 3 löst:
trait SoftDeletable[CaseClass] extends BaseModel[CaseClass] { ... }
class Models extends BaseModel[Model]("models") with SoftDeletable[Model] { ... }
keine Antwort per se, aber wenn Sie eine Funktion aus einer Tabellentyp haben kann, die seine Spalten zurückgibt, für beide Züge, und dann kombinieren sie (f1, f2) => (t: table.type) => (f1 (t), f2 (t)), Sie haben eine Funktion, die Sie an map übergeben können. Dies entspricht Table.map (t => ((trait1col2, trait1col2), (trait2col1, trait2col2))) . – nafg
Btw Ich versuche, einen Teil dieses Problems hier anzugehen: http://stackoverflow.com/questions/11408072/trouble-getting-scala-type-inference-to-work – nafg