Magnus Magnus - 1 month ago 26
Scala Question

Scala Slick generic table trait move out of DAO

I have currently this code:

class UsersRepository @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
import driver.api._

private val Users = TableQuery[UsersTable]

def findByName(name: String): Future[Option[User]] =
db.run(Users.filter(_.name === name).take(1).result.headOption)

implicit val localDateTimeColumnType = MappedColumnType.base[LocalDateTime, Timestamp](
d => Timestamp.from(d.toInstant(ZoneOffset.ofHours(0))),
d => d.toLocalDateTime
)

trait GenericTable {
this: Table[_] =>
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def createdAt = column[LocalDateTime]("created_at")
def updatedAt = column[LocalDateTime]("updated_at")
}

private class UsersTable(tag: Tag) extends Table[User](tag, "User") with GenericTable {

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

def nameIndex = index("name_index", name, unique = true)

override def * = (id, createdAt, updatedAt, name, url) <> (User.tupled, User.unapply)
}

}


How can I now easily move the GenericTable trait out of the UsersRepository so that I can use it with other tables? If I just move it out, then things like
column
,
Table
and
O
are not found anymore, because I loose the things from the driver import.

I also would like to move the
UsersTable
definition itself out of the DAO/repository class. I have the same problem in this case.

Thanks,
Magnus

Answer

Provider dbConfig in the trait as a no input parameter def

trait GenericTableProvider {
  val dbConfig: DatabaseConfig[JdbcProfile]
  import dbConfig.driver.api._

  trait GenericTable {
      this: Table[_] =>

      def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
      def createdAt = column[LocalDateTime]("created_at")
      def updatedAt = column[LocalDateTime]("updated_at")
    }

}

and then use it as shown in the code snippet below.

class UsersRepository @Inject()(protected override val dbConfigProvider: DatabaseConfigProvider) 
  extends HasDatabaseConfigProvider[JdbcProfile] 
  with GenericTableProvider {

  import driver.api._

  private val Users = TableQuery[UsersTable]

  private class UsersTable(tag: Tag) extends Table[User](tag, "User") with GenericTable {

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

    def nameIndex = index("name_index", name, unique = true)

    override def * = (id, createdAt, updatedAt, name, url) <> (User.tupled, User.unapply)
  }
  .....

 }

override def dbConfigProvider with a val dbConfigProvider