Joseph Lust
Joseph Lust

Reputation: 19985

Creating Implementation of DatabaseConfigProvider

I'm trying to test a Slick Play app without having to startup and run everything through a Play Application context (using H2). This is because I want to share H2 connections and do a lot of test DB prep before hand.

To do so, I need a DatabaseConfigProvider implementation. In this case, I need a JdbcProfile config. The trait I'm extending is:

trait DatabaseConfigProvider {
  def get[P <: BasicProfile]: DatabaseConfig[P]
}

However, I cannot get the signature of DatabaseConfigProvider's method to type check.

class TestDbProvider(config:DatabaseConfig[JdbcProfile]) extends DatabaseConfigProvider {
  def get[P <: BasicProfile]: DatabaseConfig[P] = config
}

The above implementation, and many other variants all fail.

[error] RepositoryTest.scala:78: type mismatch;
[error]  found   : slick.backend.DatabaseConfig[slick.driver.JdbcProfile]
[error]  required: slick.backend.DatabaseConfig[P]
[error]     def get[P <: BasicProfile]: DatabaseConfig[P] = config
[error]                                                     ^
[error] one error found
[error] (api/test:compileIncremental) Compilation failed

More bad variants:

// Fails
class TestDbProvider(config:DatabaseConfig[JdbcProfile]) extends DatabaseConfigProvider {
  def get[P <: BasicProfile]: DatabaseConfig[JdbcProfile] = config
}

// Fails
class TestDbProvider[P <: BasicProfile](config:DatabaseConfig[P]) extends DatabaseConfigProvider {
  def get[P]: DatabaseConfig[P] = config
}

// Fails
class TestDbProvider(config:DatabaseConfig[JdbcProfile]) extends DatabaseConfigProvider {
  def get[JdbcProfile]: DatabaseConfig[JdbcProfile] = config
}

What's the trick in Scala to make an implementation of DatabaseConfigProvider? Looking through Slick/Play's code base, there is no example of such a concrete implementation.

Upvotes: 2

Views: 350

Answers (1)

Joseph Lust
Joseph Lust

Reputation: 19985

We couldn't find anyway to make this work without using casting. Here is my implementation:

def toProvider(dbIn: PostgresDriver.backend.DatabaseDef) = {

    new DatabaseConfig[JdbcProfile] {

      override def db: JdbcProfile#Backend#Database = dbIn
      override def config: Config = None.orNull // unused
      override def driverIsObject: Boolean = true
      override def driverName: String = "org.postgresql.Driver"
      override val driver: JdbcProfile = ExtendedPostgresDriver
    }

    new DatabaseConfigProvider {
      // Cast is necessary, otherwise cannot get to compile
      override def get[P <: BasicProfile]: DatabaseConfig[P] = config.asInstanceOf[DatabaseConfig[P]]
    }
}

Upvotes: 1

Related Questions