In slick you write a projection that:
defines how the columns are converted to and from the Person object.
the default format is:
def * = (id, name, age) <> ((Person.apply _).tupled, Person.unapply)
We can use it to directly map classes/tuples to database tables.
Can you use it to alter values as part of the conversion?
E.g. purely as an example, could you set a constant value in the Person object, but ignore it in the database? Or map the name as a String in the database, and as an enum in the Person object?
The following code compiles
import slick.jdbc.PostgresProfile.api._
trait Name
object Name {
case class Ordinary(s: String) extends Name
case class Manager(s: String) extends Name
case object NoName extends Name
}
case class Person(id: Long, name: Name, age: Int, isValid: Boolean)
class Persons(tag: Tag) extends Table[Person](tag, "persons") {
def id = column[Long]("id", O.PrimaryKey)
def name = column[String]("name")
def age = column[Int]("age")
def * = (id, name, age) <> ({
case (l, "NoName", i) => Person(l, Name.NoName, i, true)
case (l, s, i) if s.startsWith("Mgr.") => Person(l, Name.Manager(s.stripPrefix("Mgr.")), i, true)
case (l, s, i) => Person(l, Name.Ordinary(s), i, true)
}, (p: Person) => p.name match {
case Name.Ordinary(s) => Some((p.id, s, p.age))
case Name.Manager(s) => Some((p.id, "Mgr." + s, p.age))
case Name.NoName => Some((p.id, "NoName", p.age))
})
}
Here we set isValid
to be a constant value and map name
to enum.