Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slick: combine actions with a Seq of DBIOAction

I have the (working) following code:

val actions = (for {
  _ <- slickUsers.insertOrUpdate(dbUser)
  loginInfo <- loginInfoAction
  _ <- slickUserLoginInfos += DBUserLoginInfo(dbUser.userID, loginInfo.id.get)
} yield ()).transactionally

with loginInfoAction being a DBIOAction. I would like to change loginInfoActions to a Seq of DBIOAction and for each of them, execute the same DBUserLoginInfo action afterwards.

I tried this stupidly:

val actions = (for {
  _ <- slickUsers.insertOrUpdate(dbUser)
  loginInfoAction <- loginInfoActions
  loginInfo <- loginInfoAction
  _ <- slickUserLoginInfos += DBUserLoginInfo(dbUser.userID, loginInfo.id.get)
} yield ()).transactionally

But it does not work as expected (I would have though loginInfoAction would iterate over the Seq of DBIOAction). I am a newbie in Slick so do not hesitate to point me to the documentation if I missed anything !

like image 374
CanardMoussant Avatar asked Nov 23 '16 07:11

CanardMoussant


1 Answers

DBIO.sequence

Use DBIO.sequence to convert List[DBIO[_]] to DBIO[List[_]] and use for-comprehension.

DBIO.sequence will convert the sequence of DBIO's into DBIO[Seq[_]].

For example let say we have a function getUser

def getUser(userId: Long): DBIO[User]

def getAllUsers(userIds: List[Long]): DB[List[User]] = {
  DBIO.sequence(userIds.map(getUser))
}

DBIO.Sequence converts List[DBIO[_]] to DBIO[List[_]]

Now your code becomes

val actions = (for {
  _ <- slickUsers.insertOrUpdate(dbUser)
  loginInfoActionList <- DBIO.sequence(loginInfoActions)
  _ <- DBIO.sequence { loginInfoActionList.map { loginInfo =>
           slickUserLoginInfos += DBUserLoginInfo(dbUser.userID, loginInfo.id.get) }
      }
} yield ()).transactionally
like image 162
pamu Avatar answered Oct 10 '22 17:10

pamu