I have find a way to update database models from http requests as below;
case class DatabasePerson(
id: Int,
name: Option[String],
surname: String
)
case class PersonUpdateRequest(
name: Option[String],
surname: Option[String]
) {
def update(databasePerson: DatabasePerson) = databasePerson.copy(
name = name.orElse(databasePerson.name),
surname = surname.getOrElse(databasePerson.surname)
)
}
with this way i am able to update the only sent fields from the client. Which i believe sending only the updated (or touched) fields to the api preferred way in technologies such as react.
My problem starts if a person needs to delete an optional field from the db. In the example it can be the name value
Only way comes to my mind is expecting an invalid value, such as "" maybe. So adjusting the update model for such agreement would be something like below;
case class PersonUpdateRequest(
name: Option[String],
surname: Option[String]
) {
def update(databasePerson: DatabasePerson) = databasePerson.copy(
name = if (name.exists(_.isEmpty)) None else name.orElse(databasePerson.name),
surname = surname.getOrElse(databasePerson.surname)
)
}
this was only for string but i also have dates, numbers or complex models. And as you can see it is a bit tedious to write for all the fields.
I am using play framework for validation, so there is a mapper like this for the update request;
object PersonUpdateRequest {
lazy val map = mapping(
"name" -> optional(text),
"surname" -> optional(text)
)(apply)(unapply)
}
What would be the preferred way to delete optional fields on update methods. Thanks.
One way you could do this that would fit your data model is to add an other level of Option on your option:
case class PersonUpdateRequest(
name: Option[String],
surname: Option[Option[String]]
)
so you can have those cases:
surname == Some(Some("foo")) // set surname to "foo"
surname == Some(None) // set surname to None == delete the value in the db
surname == None // do not update
This would imply to use a custom mapper. This might work with a custom json reader Reads[Option[Option[T]]. Something like:
JsUndefined => None
JsNull => Some(None)
JsString(value) => Some(Some(value)
But I'm not sure about how to use it with a Form
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With