2015-12-04 24 views
7

Sono nuovo di Scala e anche quello che sto cercando di ottenere è troppo semplice con Java, mi sento confuso con Scala.Ottieni utente e carica tutti i permessi

Quello che voglio è quello di ottenere un User e poi riempire il suo Permission utilizzando un'altra query e si basa per la sua Role e la sua individuale Permissions.

Fino so di avere il seguente codice:

/** 
* Finds a user by its loginInfo. 
* 
* @param loginInfo The loginInfo of the user to find. 
* @return The found user or None if no user for the given login info could be found. 
*/ 
def find(loginInfo: LoginInfo): Future[Option[models.admin.User]] = { 

val userQuery = for { 
    dbLoginInfo <- loginInfoQuery(loginInfo) 
    dbUserLoginInfo <- Userlogininfo.filter(_.logininfoid === dbLoginInfo.id) 
    dbUser <- User.filter(_.userid === dbUserLoginInfo.userid) 
    user <- dbUser match { 
    case u => 
     val permissionQuery = for { 
     dbUserPermission <- Userpermission.filter(_.userid === u.userid) 
     dbPermission <- Permission.filter(_.id === dbUserPermission.permissionid) 
     } yield dbPermission 

     val rolePermissionQuery = for { 
     dbUserRole <- Userrole.filter(_.userid === u.userid) 
     dbRole <- Role.filter(_.id === dbUserRole.roleid) 
     dbRolePermission <- Rolepermission.filter(_.roleid === dbRole.id) 
     dbPermission <- Permission.filter(_.id === dbRolePermission.permissionid) 
     } yield dbPermission 

     val unionPermissionQuery = permissionQuery union rolePermissionQuery 

     db.run(unionPermissionQuery.result).map(_.map(_.name).toList).map { permission => 

     models.admin.User(
      UUID.fromString(u.userid.toString), 
      u.firstname.toString, 
      u.lastname.toString, 
      u.jobtitle.toString, 
      loginInfo, 
      u.email.toString, 
      false, 
      Some(permission), 
      false) 
     } 
    case None => None 
    } 
} yield user 

db.run(userQuery.result.headOption) 

} 

ho ottenuto le seguenti errori:

pattern type is incompatible with expected type; 
[error] found : None.type 
[error] required: UserDAOImpl.this.User 
[error]   case None => None 
[error]   ^
[error] play/modules/admin/app/models/daos/impl/UserDAOImpl.scala:36: value map is not a member of Object 
[error]  user <- dbUser match { 
[error]     ^
[error] play/modules/admin/app/models/daos/impl/UserDAOImpl.scala:34: type mismatch; 
[error] found : UserDAOImpl.this.Userlogininfo => slick.lifted.Query[Nothing,Nothing,Seq] 
[error] required: UserDAOImpl.this.Userlogininfo => slick.lifted.Query[Nothing,T,Seq] 
[error]  dbUserLoginInfo <- Userlogininfo.filter(_.logininfoid === dbLoginInfo.id) 
[error]      ^
[error] play/modules/admin/app/models/daos/impl/UserDAOImpl.scala:33: type mismatch; 
[error] found : UserDAOImpl.this.Logininfo => slick.lifted.Query[Nothing,Nothing,Seq] 
[error] required: UserDAOImpl.this.Logininfo => slick.lifted.Query[Nothing,T,Seq] 
[error]  dbLoginInfo <- loginInfoQuery(loginInfo) 
[error]     ^
[error] play/modules/admin/app/models/daos/impl/UserDAOImpl.scala:69: value headOption is not a member of UserDAOImpl.this.driver.DriverAction[Seq[Nothing],UserDAOImpl.this.driver.api.NoStream,slick.dbio.Effect.Read] 
[error]  db.run(userQuery.result.headOption) 
[error]       ^
[error] 5 errors found 
+1

'case u =>' corrisponderà a qualsiasi cosa. Se vuoi modificare l'opzione se è 'Some' e lasciare 'None' otherways puoi usare' map'. Non so davvero come aiutare con altre cose, dato che non conosco le chiacchiere, ma forse cerco di annotare i tipi che ti aspetti e lascia che il compilatore ti dica dove fallisci. –

+1

I messaggi di errore che stai ricevendo, se li leggi attentamente, ti stanno già dicendo quali sono i tuoi problemi. C'è un particolare messaggio di errore in cui hai difficoltà a interpretare ...? –

+0

Sarà più facile eseguire il debug se è possibile fornire gli schemi delle tabelle e i metodi. – mohit

risposta

0

Ogni volta che si lavora con un per-la comprensione con una yield dovete capire che un lavorando con una sorta di valore "incartato" (monade). Può essere un Future, un List, uno Option o qualsiasi altra cosa che è monadico.

Così il modello è un po 'come questo:

for { 
    someValue <- someWrappedValue() 
    someOtherValue <- someWrappedOtherValue(someValue) 
} yield someOtherValue 

Se si lavora con Future, quindi è possibile utilizzare queste regole:

  • Tutto a destra di un <- deve essere un Future
  • Tutto a sinistra di un <- è il valore "unwrapped"
  • Il valore di tutto il per-la comprensione sarà tutto ciò che è sulla yield avvolti in un Future

Le regole sono le stesse per List, Option, ecc, ma non è possibile combinare all'interno dello stesso per-comprensione.

Uno degli errori suggerisce che il risultato dell'istruzione match è di tipo Object, il che significa che scala non è riuscito a capire un tipo comune per tutti i casi nella corrispondenza. Si desidera che tutti i casi producano un Future (poiché questo è ciò con cui stiamo lavorando in questa comprensione preliminare).

La mia ipotesi, è necessario sostituire:

case None => None 

con:

case None => Future.successful(None) 

Ma è difficile sapere con certezza, senza ulteriori informazioni.

Per quanto sia più semplice in Java: non esattamente. Ciò che lo rende un po 'più complesso non è il linguaggio, ma il fatto che molti metodi siano asincroni. Se lo si facesse in sincrono in scala, sarebbe semplice come java, se non di più. Ma poi si bloccherebbe un thread ogni volta che si stanno aspettando dei risultati, come nel caso di java (assumendo le chiamate sincrone).