0

I have a slick table "UserSchema" as follows:

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

  def name = column[String]("name", O.NotNull)
  def password = column[String]("password", O.NotNull)
  def graduatingYear = column[Int]("graduating_year", O.NotNull)
  def id = column[Int]("id", O.NotNull, O.PrimaryKey, O.AutoInc)

  def * = (name, password, graduatingYear, id.?) <> (User.tupled, User.unapply)

}

My "User" case class is as follows:

case class User(name: String, password: String, graduatingYear: Int, id: Option[Int] = None)

I have a TableQuery[UserSchema] in a users object, and a database in a db object.

How can I convert the following into a User object?

db withSession { implicit session =>
  users.filter(_.id === 1)
}

At the moment, I have

db withSession { implicit session =>
    val list = users.filter(_.id === id).list
    list(0)
}

which works, but seems ugly to me. Is there a better way to do this?

Thanks for the help.

davenportw15
  • 157
  • 2
  • 10

2 Answers2

1

You can use a map on the Slick query like this:

db withSession { implicit session =>
  val userlist = users.filter(_.id === id).list
    .map(user => User(user._1, user._2, user._3, Some(user._4)))
}

where userlist is a collection of User.

kdrakon
  • 172
  • 1
  • 8
  • You don't need to map since the conversion to the case class is automatically executed by slick once you provide the [projection function (*)](http://stackoverflow.com/questions/13906684/scala-slick-method-i-can-not-understand-so-far). – Ende Neu Aug 11 '14 at 06:57
  • Thanks Ende! Didn't know that was possible. Found this link (http://blog.lunatech.com/2013/11/21/slick-case-classes) that also helps explain it. – kdrakon Aug 11 '14 at 13:29
  • You're welcome but note that this tutorial is for Slick 1.X, this syntax `id.? ~ name` is not used in version 2, also the answer I linked is old but it's very coincise and one of the best explaination around. – Ende Neu Aug 11 '14 at 13:31
1

The list() method returns a List[User] but if you are only interested in the first entry use firstOption:

db withSession { implicit session =>
  val users = TableQuery[UserSchema]
  val someUser: Option[User] = users.filter(_.id === id).firstOption
}

Which returns Some(User) if the query found something, else None, this is also more safe as it could happen that the query has no result and calling list(0) could result in an exception.

Ende Neu
  • 15,581
  • 5
  • 57
  • 68