2016-09-16 2 views
0

Ich möchte eine Methode implementieren, die einen Benutzer erstellt, wenn es noch nicht existiert. Wenn es existiert, sollte der Benutzer zurückgegeben werden.So entpacken Sie die Option in Zukunft?

Hier ist mein Code:

def createUserIfNotExists(user: User) = { 
for { 
    count <- userService.count(Some(user)) 
    user <- if (count == 0) createUser(user) else userService.findOneByName(user.name) 
} yield user 
} 

Mein Problem ist, dass findOneByName kehrt Future[Option[User]] und createUser kehrt Future[User] so die Typen nicht übereinstimmen.

Wie kann ich Future[Option[User]] zu Future[User] auspacken oder eine Ausnahme auslösen, wenn es None gibt?

+1

Das 'for' Verständnis dient keinem Zweck. – jwvh

+0

@jwvh Warum? Könnten Sie bitte erklären? –

+0

SO Kommentare erlauben mir nicht, formatierten Code zu präsentieren, aber CNTL-Kopieren Sie die folgenden und fügen Sie Whitespace nach Geschmack: 'def createUserIfNotExists (Benutzer: Benutzer) = if (userService.count (Einige (Benutzer))> 0) userService .findOneByName (user.name) sonst createUser (user) ' – jwvh

Antwort

2

machen createUser auch Future[Option[_]]

def createUserIfNotExists(user: User) = { 
    for { 
    count <- userService.count(Some(user)) 
    userOpt <- if (count == 0) createUser(user).map(Some(_)) else userService.findOneByName(user.name) 
    } yield userOpt 
} 

oder

Sie zurückkehren können .get auf die Option tun, denn wenn Zählung nicht Null, die Benutzereinrichtung in der Datenbank auf jeden Fall zur Verfügung.

def createUserIfNotExists(user: User) = { 
    for { 
    count <- userService.count(Some(user)) 
    user <- if (count == 0) createUser(user) else userService.findOneByName(user.name).map(_.get) 
    } yield user 
} 

oder

Zuerst versuchen, den Benutzer abzurufen, wenn nicht der Benutzer erstellen

def createUserIfNotExists(user: User) = { 
for { 
    userOpt <- userService.findOneByName(user.name) 
    user <- userOpt match { 
     case Some(value) => value 
     case None => createUser(user).map(_ => user) 
    } 
} yield user 
} 

Beachten Sie, dass Korrektheit bei parallelen Datenbankoperationen, um sicherzustellen, es ist sehr zu empfehlen auszuführen Der obige Code in einem transaction

+0

Ihre dritte Antwort wird nicht kompiliert. Sie mischen Typen zum Verständnis. – wheaties

+0

@Wheaties .. bearbeitete die Antwort .. Bitte überprüfen ... Ich habe mich nicht Gedanken über Typen als vollständiger Code ist nicht in den Fragen befriedigende Compiler ist dem Benutzer überlassen. Ich bin daran interessiert, die Hauptidee zu geben (nur der Kern der Lösung) – pamu

2

Gerade map die createUser Funktion Rückgabetyp:

if (count == 0) createUser(user).map(Option(_)) else userService.findOneByName(user.name) 

Die Tatsache, dass der Rückgabetyp von findOneByName enthält ein Option schlägt vor, dass Sie keinen Benutzer haben könnte. Dieser Typ existiert aus einem bestimmten Grund, also ist es schlecht, ihn wegzuwerfen, weil er Informationen wegwirft.

1

Verwendung die findOneByName Funktion direkt, so dass Sie die DB nicht zweimal abfragen müssen:

Verwandte Themen