Получить пользователя и заполнить все разрешения
Я новичок в Scala, и даже то, что я пытаюсь достичь, слишком просто с Java, я чувствую себя запутанным со Scala.
Я хочу получить User
а затем заполнить его Permission
используя другой запрос и основанный на его Role
и его личность Permissions
,
Пока не знаю, у меня есть следующий код:
/**
* 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)
}
Я получил следующие ошибки:
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 ответ
Всякий раз, когда вы работаете с для понимания с yield
Вы должны понимать, что вы работаете с каким-то "обернутым" значением (монадой). Это может быть Future
, List
, Option
или что-нибудь еще, что является монадическим.
Итак, шаблон выглядит примерно так:
for {
someValue <- someWrappedValue()
someOtherValue <- someWrappedOtherValue(someValue)
} yield someOtherValue
Если вы работаете с Future
Тогда вы можете использовать эти правила:
- Все справа от
<-
должен бытьFuture
- Все слева от
<-
это "развернутый" значение - Ценность всего для понимания будет то, что на
yield
завернутый вFuture
Правила одинаковы для List
, Option
и т. д. Но вы не можете смешивать и сочетать в одном и том же для понимания.
Одна из ошибок намекает на то, что результат вашего match
заявление имеет тип Object
Это означает, что scala не может определить общий тип для всех случаев в матче. Вы хотите, чтобы все дела производили Future
(так как это то, с чем мы работаем в этом для понимания).
Я думаю, вам нужно заменить:
case None => None
с:
case None => Future.successful(None)
Но трудно знать наверняка без дополнительной информации.
Относительно того, как это проще в Java: не совсем так. Что делает его немного более сложным, так это не язык, а тот факт, что многие методы являются асинхронными. Если бы вы делали это синхронно в Scala, это было бы так же просто, как в Java, если не больше. Но тогда вы будете блокировать поток каждый раз, когда ожидаете результатов, как в случае с Java (при условии синхронных вызовов).