Reputation: 7101
I have the following code:
Some(db.run(unionPermissionQuery.result).map(_.map(_.name).toList))
and I get the following error:
[error] found : scala.concurrent.Future[List[String]]
[error] required: List[String]
[error] Some(db.run(unionPermissionQuery.result).map(_.map(_.name).toList)),
[error] ^
[error] one error found
So I suppose I have to convert the Future[List[String]]
to List[String]
. I am new to scala sorry if that's too easy.
Full code:
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)
} yield dbUser
db.run(userQuery.result.headOption).map { dbUserOption =>
dbUserOption.map { user =>
val permissionQuery = for {
dbUserPermission <- Userpermission.filter(_.userid === user.userid)
dbPermission <- Permission.filter(_.id === dbUserPermission.permissionid)
} yield dbPermission
val rolePermissionQuery = for {
dbUserRole <- Userrole.filter(_.userid === user.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
models.admin.User(
UUID.fromString(user.userid),
user.firstname,
user.lastname,
user.jobtitle,
loginInfo,
user.email,
user.emailconfirmed,
Some(db.run(unionPermissionQuery.result).map(_.map(_.name).toList)),
user.enabled)
}
}
I just want to get the user and then fill all permissions. Individual permissions and permissions inherited by the role assigned to the user.
Is it better to get the user and then perform another request to get the permissions based on the user id? I don't think so.
Upvotes: 3
Views: 6205
Reputation: 28680
I'm answering the question in the title.
The only way to implement the function Future[A] => A
in a sensible way (and without access to a time-machine) is to await the completion of the future, as a value Future[A]
indicates a value of type A
will yield in the future.
Check your library for the correct method to wait. For the Scala std lib it is As commented by Jean, the correct way for the Scala std lib is to use .result
.Await.result()
.
Note that waiting is a blocking method call. If you want to avoid this (and there are some good reasons to do so), you should check out Andreas' answer.
Upvotes: 2
Reputation: 10884
You will find all information on Futures you need on http://docs.scala-lang.org/overviews/core/futures.html.
A possible approach is awaiting the result, but it is not good to use in a prod application.
val myFutureResult : Future[T] = Future {...}
val myResult : T = Await.result(myFutureResult, secondsToWait seconds)
Normally instead of awaiting the result and storing it in a variable you can map
the future and compose it and only use Await at the last moment.
val myFutureResult : Future[T] = Future {...}
def myFunctionOnT(in: T) = ...
for {res <- myFutureResult } yield myFunctionOnT(res)
Play itself can handle Future[T]
by default by using Action.async {}
instead of Action{}
here you can find more: https://www.playframework.com/documentation/2.5.x/ScalaAsync
db.run(unionPermissionQuery.result).map(_.map(_.name).toList).map { permission =>
models.admin.User(
UUID.fromString(user.userid),
user.firstname,
user.lastname,
user.jobtitle,
loginInfo,
user.email,
user.emailconfirmed,
Some(permission),
user.enabled)
}
Upvotes: 6