Implicite dans la correspondance de modèle
-
10-12-2019 - |
Question
J'ai une méthode, avec beaucoup de paramètres implicites :
def hello(message:String)(implicit a:A,b:B,c:C, ..., user: User) = {...}
Considérons maintenant une telle classe :
object Users extends Controller {
implicit a: A = ...
implicit b: B = ...
...
def index(id:String) = Action {
User.findById(id) match {
case Some(user) => {
implicit val _user = user
hello("implicit")
}
case _ => BadRequest
}
}
}
Vous pouvez voir cette ligne dans l'exemple ci-dessus :
implicit val _user = user
Il existe juste pour fabriquer l'objet user
comme objet implicite.Sinon, je dois appeler hello
comme:
hello("implicit")(a,b,c,... user)
Je me demande s'il existe un moyen d'améliorer le code, par ex.nous n'avons pas besoin de définir cela _user
variable mais faire le user
est implicite.
La solution
Oui, il existe un moyen d'éliminer _user
variable lors de la création user
implicite:
def index(id:String) = Action {
User.findById(id) map (implicit user => hello("implicit")) getOrElse BadRequest
}
MISE À JOUR: Répondant à votre question sur de nombreux cas dans les commentaires ci-dessous.
Tout dépend du type de valeur renvoyé par User.findById
.Si c'est Option[User]
mais vous souhaitez faire correspondre des utilisateurs spécifiques (en supposant User
est une classe de cas), alors la solution originale s'applique toujours :
def index(id:String) = Action {
User.findById(id) map { implicit user =>
user match {
case User("bob") => hello("Bob")
case User("alice") => hello("Alice")
case User("john") => hello("John")
case _ => hello("Other user")
}
} getOrElse BadRequest
Ou vous pouvez faire correspondre n'importe quoi d'autre si vous le souhaitez, à condition que User.findById
est String => Option[User]
Si, par contre, User.findById
est String => User
alors vous pouvez simplement définir un objet d'assistance comme :
object withUser {
def apply[A](user: User)(block: User => A) = block(user)
}
Et utilisez-le comme suit (en supposant encore une fois User
est une classe de cas) :
def index(id: String) = Action {
withUser(User findById id) { implicit user =>
user match {
case User("bob") => hello("Bob")
case User("alice") => hello("Alice")
case User("john") => hello("John")
case _ => BadRequest
}
}
}
ou une correspondance sur une autre valeur, disons un Int
:
def index(id: String, level: Int) = Action {
withUser(User findById id) { implicit user =>
level match {
case 1 => hello("Number One")
case 2 => hello("Number Two")
case 3 => hello("Number Three")
case _ => BadRequest
}
}
}
J'espère que cela couvre tous les scénarios que vous pourriez avoir.
Autres conseils
Je ne connais aucune astuce comme celle-ci Some(implicit user)
mais qu'en est-il
def hello(message: String, user: User)(implicit a: A, ... z: Z) = ...
def hello(message: String)(implicit a: A, ... z: Z, user: User) = hello(message, user)
case Some(user) => hello("implicit", user)