2012-06-03 1 views
13

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:

  1. Wie kann ich komponieren sauber die Filter in SoftDeletable.allQuery und die Art in SortedByName.allQuery mit BaseModel.allQuery?

  2. von Spalten in der Unterklasse Implementierungen der * Methode hinzufügen, die Tupel-Typ-Parameter auf Table 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).

  3. 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] { ... } 
+0

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

+0

Btw Ich versuche, einen Teil dieses Problems hier anzugehen: http://stackoverflow.com/questions/11408072/trouble-getting-scala-type-inference-to-work – nafg

Antwort

1

Wenn Ihr Problem ist nur die Art hinzufügen, ist es nicht nur eine Frage des flatMap?

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