问题
I have the following objective: Create a monad that adds an user with the following computation flow:
- Check if an user exists with a specified e-mail, if he doesn't then :
- Check if the credentials given are ok (password long enough, etc.). If they are ok, then:
- 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.
回答1:
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
}
来源:https://stackoverflow.com/questions/37334335/filtering-and-mixing-monads-in-slick-for-comprehension-and-cats