I have the following Scala/Slick/PlayFramework code:
class UserRepository @Inject()(dbConfigProvider: DatabaseConfigProvider, loginInfoRepository: LoginInfoRepository) extends BaseRepository[UserTable, User](TableQuery[UserTable], dbConfigProvider.get[JdbcProfile].db) with UserQuery {
val db = dbConfigProvider.get[JdbcProfile].db
def findUserByProviderIdAndKey(providerId: String, providerKey: String): Future[User] = {
for {
maybeLoginInfo <- loginInfoRepository.findByProviderIdAndProviderKey(providerId, providerKey)
maybeUser <- db.run(query.filter(_.loginId === maybeLoginInfo.loginId).result.head) //query refers to the user table with a loginId column
} yield maybeUser
}
Which queries a user table and a login_info table. The user table has a foreign key into login_info table.
Currently, the findByProviderIdAndProviderKey
method returns a Future[LoginInfo]
. However, I would like to change it to return a Future[Option[LoginInfo]]
for user id's that don't exist. It can be easily changed in the findByProviderIdAndProviderKey
method, but I'm not sure how the change for comprehension to deal with an option value.
I guess I could to something like below (needs refactoring):
class UserRepository @Inject()(dbConfigProvider: DatabaseConfigProvider, loginInfoRepository: LoginInfoRepository) extends BaseRepository[UserTable, User](TableQuery[UserTable], dbConfigProvider.get[JdbcProfile].db) with UserQuery {
val db = dbConfigProvider.get[JdbcProfile].db
def findUserByProviderIdAndKey(providerId: String, providerKey: String): Future[User] = {
loginInfoRepository.findByProviderIdAndProviderKey(providerId, providerKey).map{
case (Some(x)) => db.run(query.fitler(_.loginId == x.loginInd).result.headOption)
case None=> Option(None)
}
Now, I have the following questions:
How would you deal with the query not returning values for a given query? For instance, if the login information doesn't exist in the table? Am I doing it the right way? Or is there a better way?
I would have thought that slick caters for
Option
values automatically in joins, but seems like it does not. Why areOption
values not lifted?Would the above be translated into two SQL queries and database calls? If yes, how do I re-structure it so it only issues one database call with a proper join?
Thanks in advance!
findByProviderIdAndProviderKey
method, could you also post the code for this? – thwiegan