Comment peut on retourner une erreur en fonction d’un futur sous Vapor ?
Avant de créer un utilisateur, je veux verifier si il est deja enregistré et si l’username choisit existe deja.
Sinon, retourner l’erreur correspondante.
Je n’arrive pas à trouver un moyen de tout imbriquer…
enum UserError {
case usernameTaken
case emailTaken
}
extension UserError: AbortError {
var description: String {
reason
}
var status: HTTPResponseStatus {
switch self {
case .usernameTaken: return .conflict
case .emailTaken: return .conflict
}
}
var reason: String {
switch self {
case .usernameTaken: return "Username already taken"
case .emailTaken: return "Email already registered"
}
}
}
private func checkIfUserExists(_ username: String, _ email: String, req: Request) -> EventLoopFuture<UserError?> {
// Si l'username existe deja -> Retourner l'erreur .usernameTaken
User.query(on: req.db)
.filter(\.$username == username)
.first()
.map { $0 != nil }
return req.eventLoop.future(error: UserError.usernameTaken)
// Si l'email existe deja -> Retourner l'erreur .emailTaken
User.query(on: req.db)
.filter(\.$email == email)
.first()
.map {
if $0 != nil { return UserError.emailTaken }
}
}
Le cours de Maxime « Créer un webservice en Swift avec Vapor 4 » sur Vapor/Fluent est très intéressant.
Malheureusement, j’ai beau regarder la partie sur les valeurs futur (map/flatmap/transform), jej e comprends pas commet faire…
ça fait partie de choses que je regarderais à tête reposé quand j’aurais du temps libre devant moi. Pour le moment, mon carnet de bal est rempli, pour les 6 prochains mois (minimum)…
Je n’ai encore jamais fait ça mais, tu captures les erreurs avec catch ou throw et après tu fais une condition ou tu utilises un guard pour lancer l’erreur avec catch ou throw suivant si ta fonction propage ou pas les erreurs.
Je n’ai pas réussi a faire ce que je voulais en retournant directement une erreur spécifique et je n’arrive pas non plus à retourner un false au lieu d’un true…
Mais bon, le code suivant fonctionne donc je ne vais pas perdre plus de temps et l’utiliser jusqu’à ce que je sois plus compétent pour le modifier dans une version ultérieure…
Je met la partie de code ici si ça intéresse quelqu’un :
fileprivate func create(req: Request) throws -> EventLoopFuture<NewSession> {
let userSignup = try req.content.decode(UserSignup.self)
let user = try User.create(from: userSignup)
return checkIfEmailExists(userSignup.email, req: req).flatMap { emailExists in
guard emailExists else {
return req.eventLoop.future(error: UserError.emailTaken)
}
return checkIfUsernameExists(userSignup.username, req: req).flatMap { usernameExists in
guard usernameExists else {
return req.eventLoop.future(error: UserError.usernameTaken)
}
return user.save(on: req.db)
}
}.flatMapThrowing {
NewSession(user: try user.asPublic())
}
}
private func checkIfEmailExists(_ email: String, req: Request) -> EventLoopFuture<Bool> {
User.query(on: req.db)
.filter(\.$email == email)
.first()
.map { $0 == nil }
// -> Retourne TRUE si la valeur est NIL car je n'arrive pas a inverser la fonction
}
private func checkIfUsernameExists(_ username: String, req: Request) -> EventLoopFuture<Bool> {
User.query(on: req.db)
.filter(\.$username == username)
.first()
.map { $0 == nil }
// -> Et là aussi...
}