Marcin Gorczyński
Marcin Gorczyński

Reputation: 105

Filtering and mixing monads in Slick for comprehension and Cats

I have the following objective: Create a monad that adds an user with the following computation flow:

  1. Check if an user exists with a specified e-mail, if he doesn't then :
  2. Check if the credentials given are ok (password long enough, etc.). If they are ok, then:
  3. Save the user to the DB

My first "draft" would be something like this:

val work: DBIO[UserId] = for {
   userO <- UserRepository.findByEmail(createdUser.email) //userO is Option[User]
   //This won't work cause Action.withFilter doesnt exist
   if userO.isEmpty 
   //as above, validate user actually returns an ValidateNel[String, User]
   if User.validateUser(createdUser.email, createdUser.password).isValid 
   //Returns DBIO[UserId]
   id <- UserRepository.save(createdUser)
} yield id

Any ideas what is the best way to write this down in one monadic computation that I can db.run(...)? I'm using Cats + Slick 3.0. Also I've wrote a simple implicit dbioMonad from https://groups.google.com/forum/?fromgroups#!topic/scalaquery/HrvrvyEIopw if that helps.

Upvotes: 2

Views: 1084

Answers (1)

Paweł Jurczenko
Paweł Jurczenko

Reputation: 4471

This one doesn't use for comprehension, so let me know if that's acceptable.

val work: DBIO[UserId] = {
  UserRepository.findByEmail(createdUser.email).flatMap {
    case Some(_) => DBIO.failed(new Exception("Provided email is already taken"))
    case _ =>
      if(User.validateUser(createdUser.email, createdUser.password).isValid) {
        UserRepository.save(createdUser)
      } else {
        DBIO.failed(new Exception("User validation has failed"))
      }
  }.transactionally
}

Upvotes: 3

Related Questions