Reputation: 16345
I do updates on lifted entities using Slick. This code updates the firstName of a Contact object:
def updateContact(id: Int, firstName: Option[String]): Unit = {
val q1 = for {
c <- Contacts
if c.id is id
} yield c.firstName
// Update value with same or new value
q1.update(firstName.getOrElse(q1.list().head))
}
The option here is already useful for updating the value in case it is a Some (although it would be nicer if the update only happened if there is a new value).
What I am looking for is a way to query the object by ID, then do all the updates in memory using getOrElse and then do an update on the whole object.
Else I have to run the above for each field of the object which works but you know, feels like a dirty hack.
Upvotes: 0
Views: 1997
Reputation: 11270
Instead of q1.update(firstName.getOrElse(q1.list().head))
you can write firstName.foreach{ fn => q1.update(fn) }
which is shorter, simpler, one instead of two queries :).
Using foreach
on Option
stops looking weird when you think of it as a collection with one or zero elements.
Regarding your idea to fetch the whole object, modify it and save it back, you can do it like this:
def updateContact(id: Int, firstName: Option[String], lastName:Option[String], ...): Unit = {
val q1 = Query(Contacts).filter(_.id === id)
val c = q1.first
val modifiedC = c.copy(
firstName = firstName.getOrElse(c.firstName),
lastName = lastName.getOrElse(c.lastName),
...
)
q1.update(modifiedC)
}
Here is another example: http://sysgears.com/notes/how-to-update-entire-database-record-using-slick/
This is clean and simple and probably the best way to do it if performance is not mission critical as this always transfers all columns of Contacts
. You can save some traffic by only transferring selected columns.
Upvotes: 3