2
votes

I want to filter rows by column which I don't want to see in my domain class. So for example my table looks like this:

  class UserTable(tag: Tag) extends Table[(Int, String, Boolean)](tag, "users") {

    def id = column[Int]("id")

    def name = column[String]("name")

    def active = column[Boolean]("active")

    override def * = (id, name, active)

  }

And my domain class like this:

case class User(id: Int, name: String)

For some reason I don't want to have filed active in my User class. But I want to have queries which produces User as a result. And I don't want to map futures. Like this:

val activeUsers: Future[Seq[User]] = db.run(query.filter(_.active === true) /* how to convert it here? */)

So my problem could be solved in two ways. Define UserTable like UserTable[User] and still somehow filter it by active column. Or define UserTable as it defined now and convert tuples to User class. I almost sure that the first one is not possible, but the second one should be possible. How to do this?

1

1 Answers

0
votes

I've played a little with Slick. If I don't miss something, what seemed impossible to me is actually very easy and I can use column which is not present in the end class in queries :

object SlickMain {

  def main(args: Array[String]) {

    import scala.concurrent.ExecutionContext.Implicits.global

    val db = Database.forConfig("slick.db")

    val query = TableQuery[UserTable]

    await {
      db.run(query ++= Seq(
        User(1, "first"),
        User(2, "second")
      ))
    }

    val users = for {
      nonActiveUsers <- query.filter(_.active === false).result
      _ <- DBIO.sequence(nonActiveUsers.map(us => query.filter(_.id === us.id).map(_.active).update(true)))
    } yield nonActiveUsers

    val firstResult: Seq[User] = await(db.run(users))
    println(s"First batch: $firstResult")
    // prints vector with two users

    val secondResult: Seq[User] = await(db.run(users))
    println(s"Second batch: $secondResult")
    // prints empty vector
  }

  def await[T](f: => Future[T]) = Await.result(f, Duration.Inf)

  class UserTable(tag: Tag) extends Table[User](tag, "users") {

    def id = column[Int]("id")

    def name = column[String]("name")

    def active = column[Boolean]("active")

    override def * = (id, name, active) <>(create, extract)

    def create(t: (Int, String, Boolean)): User = User(t._1, t._2)

    def extract(u: User): Option[(Int, String, Boolean)] = Some((u.id, u.name, false))

  }

}


case class User(id: Int, name: String)