Получить пользователя и заполнить все разрешения

Я новичок в 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 (при условии синхронных вызовов).

Другие вопросы по тегам