2015-12-04 2 views
7

Я новичок в 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

'case u =>' будет соответствовать чему угодно. Если вы хотите изменить опцию, если она 'Some' и оставить ее« Нет », вы можете использовать« map ». Я действительно не знаю, как помочь с другими вещами, поскольку я не знаю пятна, но, возможно, попытаюсь аннотировать типы, которые вы ожидаете, и позволить компилятору рассказать вам, где вы терпите неудачу. –

+1

Сообщения об ошибках, которые вы получаете, если вы внимательно их прочтете, уже сообщают вам, в чем ваши проблемы. Есть ли определенное сообщение об ошибке, с которым вы сталкиваетесь с трудностями при интерпретации ...? –

+0

Будет легче отлаживать, если вы можете предоставить схемы ваших таблиц и методы. – mohit

ответ

0

Всякий раз, когда вы работаете с для-понимания с 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 (при условии синхронных вызовов).

Смежные вопросы