Reputation: 105
I want to update a certain column in row only if row has a valid data. Being specific: I have a table with Event
which stores start
, stop
and isActive
flag.
I would like some Events
activate by setting isActive
to true
, however I need to check if start and stop dates are valid.
model:
case class Event {start:DateTime, stop:DateTime, isActive:Boolean}
my validation method signature :
validateEvent(ev: Event): Boolean
My first approach:
def activateEv() = Action.async(parse.json) {
request => {
...
val ev = db.run(dao.findEvById(poid, uid))
val ret = ev.flatMap {
case st: Option[Event] => if (validateEvent(st.get)) {
db.run(dao.updateActivity(poid, true).map {
case 0 => false
case other => true
}
} else Future(false)
}
...
}
}
I believe that it is not the way how this problem should be addressed. Could you advice ? Maybe only one db.run will be sufficient ?
Upvotes: 1
Views: 532
Reputation: 4471
This can be achieved in a single db.run
using combinators (e.g. flatMap
) on DBIOAction
objects. Assuming that your dao
methods look like that:
case object dao {
def findEvById(poid: Int, uid: Int): DBIOAction[Option[Event], NoStream, Effect.Read] = ???
// In your case `updateActivity` returns an `Int` and you're mapping it to a `Boolean`.
// That mapping could be placed here, so `updateActivity` would return `Boolean` now.
def updateActivity(poid: Int, bool: Boolean): DBIOAction[Boolean, NoStream, Effect.Write] = ???
}
This is how we can achieve the thing you're looking for:
...
val action = dao.findEvById(poid, uid).flatMap {
case Some(event) if validateEvent(event) => dao.updateActivity(poid, true)
case _ => DBIO.successful(false)
}.transactionally
db.run(action)
...
As you see we have a transaction here, which would make a selection followed by an update (only if the event
is valid). Moreover, that whole select then update
action could be a separate method in your dao
.
Upvotes: 2