Search code examples
scalaplayframeworksbtslick

Play 2.5.x: How to change the default evolutions directory location?


Is there a way to change the default evolutions directory location? I need this because I have the following apparently rare use-case:

  • For Dev/Prod I use a default database Postgres
  • For Unit testing I need to use an H2 in-memory database
  • evolutions/default/1.sql is portable (Postgres & H2)
  • evolutions/default/2.sql is non portable Postgres script
  • In Dev/Prod I need evolutions to run 1.sql and 2.sql
  • In Unit tests I need evolutions to run only 1.sql

Is there a way to using application.conf or some sbt setting alla e.g.

javaOptions in Test += "-Dconfig.file=conf/application.test.conf"

be able to change the default directory of evolutions for test?

My OP would be solved if only I could say e.g. (theoretical doesn't work!)

javaOptions in Test += "-Devolutions.prefix=conf/testdatabase/"

and then have:

conf/
    evolutions/default/1.sql 
                       2.sql
    testdatabase/evolutions/default/1.sql -> ../../../evolutions/default/1.sql

I will be happy with any other solution for this problem that I am not aware of ... as long as it works :)


Solution

  • in your test configuration file turn off the default application of evolutions by adding this line.

    # Evolutions should not be applied by default
    play.evolutions.db.default.enabled = false
    

    Define a helper method in your test file which will apply Evolutions when called.

    import play.api.db.Database
    import play.api.db.evolutions.{DatabaseEvolutions, EvolutionsReader, ThisClassLoaderEvolutionsReader}
    
    def applyEvolutions(database: Database,
                          evolutionsToSkip: Seq[Int],
                          evolutionsReader: EvolutionsReader = ThisClassLoaderEvolutionsReader,
                          autocommit: Boolean = true,
                          schema: String = ""): Unit = {
        val dbEvolutions = new DatabaseEvolutions(database, schema)
        val evolutions = dbEvolutions.scripts(evolutionsReader).filterNot(s => evolutionsToSkip.contains(s.evolution.revision))
        dbEvolutions.evolve(evolutions, autocommit)
      }
    

    Then in your test override beforeAll and afterAll methods:

    override def beforeAll(): Unit = {
        applyEvolutions(database, Seq(2))
      }
    
      override def afterAll(): Unit = {
        Evolutions.cleanupEvolutions(database)
      }
    

    You can access database as follows:

    import play.api.db.{ DBApi, Database }
    val databaseAPI = app.injector.instanceOf[DBApi]
    val database = databaseAPI.database("default")