2

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?

Jethro
  • 3,029
  • 3
  • 27
  • 56

1 Answers1

4

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.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66