2012-10-18 3 views
8

hängt ich habe:eine abstrakte Klasse oder Eigenschaft definieren, die Rahmen-2-Code dieses Spiel (vereinfacht) auf einer impliziten

import formatters.json.IdeaTypeFormatter._ 

object IdeaTypes extends Controller { 

    def list = Action { request => 
    Ok(toJson(IdeaType.find(request.queryString))) 
    } 

    def show(id: Long) = Action { 
    IdeaType.findById(id).map { ideatype => 
     Ok(toJson(ideatype)) 
    }.getOrElse(JsonNotFound("Type of idea with id %s not found".format(id))) 
    } 
} 

IdeaType Klasse erweitert Entity, und es ist Begleiter Objekt, IdeaType, erstreckt EntityCompanion.

Wie Sie erwarten können, ich habe diese Art von Code in jedem Controller, so mag ich das grundlegende Verhalten zu einem Merkmale extrahieren, so etwas wie diese:

abstract class EntityController[A<:Entity] extends Controller { 
    val companion: EntityCompanion 
    val name = "entity" 

    def list = Action { request => 
    Ok(toJson(companion.find(request.queryString))) 
    } 
    def show(id: Long) = Action { 
    companion.findById(id).map { entity => 
     Ok(toJson(entity)) 
    }.getOrElse(JsonNotFound("%s with id %s not found".format(name, id))) 
    } 
} 

Aber ich bekomme die folgenden Fehler :

[error] EntityController.scala:25: No Json deserializer found for type List[A]. 
[error] Try to implement an implicit Writes or Format for this type. 
[error]  Ok(toJson(companion.find(request.queryString))) 
[error]   ^
[error] EntityController.scala:34: No Json deserializer found for type A. 
[error] Try to implement an implicit Writes or Format for this type. 
[error]  Ok(toJson(entity)) 
[error]    ^

ich weiß nicht, wie das die implizite Writes durch die Klassen umgesetzt werden sagen, das EntityController Merkmal (oder erben die abstrakte Klasse EntityController)

Umsetzung

- bearbeiten

bisher jetzt es so ich tue:

abstract class CrudController[A <: Entity](
    val model: EntityCompanion[A], 
    val name: String, 
    implicit val formatter: Format[A] 
) extends Controller { 

und es wie dieser ich

object CrudIdeaTypes extends CrudController[IdeaType](
    model = IdeaType, 
    name = "type of idea", 
    formatter = JsonIdeaTypeFormatter 
) 

verwenden could't scala erhalten sie automatisch wählen mit impliziert. Ich habe versucht, mit diesem Import aber nicht

import formatters.json.IdeaTypeFormatter._ 
+0

+1, haben das gleiche gedacht, wie man CRUD-Operationen in Play weg abstrahieren. Ihr Fall, JSON-Antwort, ist einfacher als mit gemischten JSON und views.html Inhalt + Authentifizierung umzugehen. Lot's o'Bastplatte ... – virtualeyes

Antwort

7

funktionierte Wenn Sie die Controler Klassen wollen sich die impliziten definieren, dann nur abstrakt implizite Werte erklären, und sie in den abgeleiteten Klassen definieren.

abstract class EntityController[A<:Entity] extends Controller { 
    protected implicit def entityWriter: Writes[A] 
    protected implicit def entityListWriter: Writes[List[A]] 
    ...  
} 

class MyEntity extends Entity { 
    ... 
} 

class MyEntityController extends EntityController[MyEntity] { 
    protected def entityWriter: Writes[MyEntity] = ... 
    protected def entityListWriter: Writes[List[MyEntity]] = ...  
} 

Es ist jedoch viel praktischer, diese implicits außerhalb der Steuerung, in der Regel in dem Begleiter Objekt Ihres Unternehmens zu definieren, so dass sie der Compiler automatisch ohne Import finden. Dann passieren die impliziten Werte an den Konstruktor von EntityController:

abstract class EntityController[A<:Entity](implicit entityWriter: Writes[A], entityListWriter: Writes[List[A]]) extends Controller { 
    ...  
} 

class MyEntity extends Entity { 
    ... 
} 
object MyEntity { 
    protected implicit def entityWriter: Writes[A] 
    protected implicit def entityListWriter: Writes[List[A]] 
} 

class MyEntityController extends EntityController[MyEntity] { 
    ... 
} 

Schlussbemerkung, die implizit zur Liste [MyEntity] wahrscheinlich nicht benötigte ist (also nur die implizite für MyEntity müssten explizit definiert werden). Ich habe nicht überprüft, aber normalerweise, wenn dieses "typeclass pattern" verwendet, das Framework wird bereits eine implizite für jede List [T] definieren, vorausgesetzt, es gibt eine implizite für T. Dies ist wahrscheinlich der Fall, obwohl ich nicht überprüft habe .