2013-06-11 2 views
0

J'utilise Play Framework et Squeryl pour créer une interface assez basique pour une base de données, mais je sais que je réécris trop de code. J'ai différents modèles pour représenter des données dans mon db, et ils le font tous les mêmes six fonctionsScala Data Modeling et Generics

object ModelType{ 
    def add(model:ModelType):Option[ModelType] = Option(AppDB.tablename.insert(model)) 
    def remove(id: Long) = AppDB.tablename.delete(id) 
    def getAll():List[ModelType] = from(AppDB.tablename)(model => select(model) orderBy(model.aDifferentFieldForEachModel)) toList 
    def toJson(model:ModelType):JsValue ={ 
     Json.toJson(
     Map("field" -> Json.toJson(model.field)) 
    ) 
    } 
    def allToJson() = { 
     val json:List[JsValue] = getAll.map{toJson(_)} 
     Json.toJson(json.toSeq) 
    } 
    def validate(different values for each model) = // is fairly different for each one. Validates the submitted fields from a user 
} 

Je suis en utilisant des classes de cas pour chacun des modèles, et en utilisant un objet d'accompagnement pour ces commandes. Comment puis-je utiliser des génériques ou des traits dans Scala pour faciliter ma vie et ne pas taper toutes ces méthodes à chaque fois?

EDIT: Résolu en grande partie avec la réponse de gzm0, mais le problème est maintenant de savoir comment implémenter getAll dans le trait? Je veux être en mesure d'enregistrer une variable pour chaque modèle qui ressemble à la model.aDifferentFieldForEachModel comme ci-dessus.

Répondre

2

Vous pouvez essayer ce qui suit:

trait ModelOps[T] { 
    def table: AppDB.Table // not sure about type 
    def order: AppDB.OrderByPredicate // not sure about type 
    def toJson(model: T): JsValue 

    def add(model: T): Option[T] = Option(AppDB.categories.insert(model)) 
    def remove(id: Long) = AppDB.categories.delete(id) 
    def getAll(): List[T] = from(table)(model => select(model) orderBy(order)) toList 
    def allToJson() = { 
    val json:List[JsValue] = getAll.map{toJson(_)} 
    Json.toJson(json.toSeq) 
    } 

} 

Ensuite, vous pouvez pour chaque type de modèle:

object ModelType extends ModelOps[ModelType] { 
    def table = AppDB.examples 
    def order = yourPredicate 
    def toJson(model:ModelType):JsValue = { 
    Json.toJson(Map("field" -> Json.toJson(model.field))) 
    } 
    def validate(different values for each model) = // is fairly different for each one. Validates the submitted fields from a user 
} 

MISE A JOUR A propos du vrai type de AppDB.OrderByPredicate:

Appel select sur PrimitiveTypeMode renvoie un SelectState. Sur ce SelectState, vous appelez orderBy qui prend un List[BaseQueryYield#O] (ou plusieurs de ceux dans la même liste d'arguments). Par conséquent, vous devez définir:

def order(model: T): List[BaseQueryYield#O] 

et

def getAll() = from(table)(model => select(model) orderBy(order(model))) toList 

Par ailleurs, BaseQueryYield#O décide de ExpressionNode.

+0

J'ai donc deux problèmes, 1: Le plus important est que chacune de ces classes étendues KeyedEntitiy [Long] et je ne sais pas comment faire ModelType étendre ModelOps [T: KeyedEntity [Long]], il doesn ' J'aime cette syntaxe. Et 2: orderBy je suppose ne prend pas un prédicat et je ne peux pas trouver dans l'API exactement ce qu'il faut mais c'est quelque chose le long de la ligne de '...) (model => select (model) orderBy (model.id)) 'et je n'ai aucune idée de comment mettre cela dans un contexte générique – kingdamian42

+0

Et 1 est fixé avec ce fil: http://stackoverflow.com/questions/8576229/scala-by-example-trait-type-parameter-with- context-bounds-erreur – kingdamian42

+0

@ kingdamian42 Message mis à jour avec le type d'ordre (anticipé) par prédicat. – gzm0