With Play 2.4 and newer, the slick plugin doesn't create evolutions any longer. For this I have added a page into development mode, that always shows the newest version of all evolutions in the browser. This approach is compatible with all coming changes in the module system, since it doesn't use any modules. An using dependency injection, it uses exactly that Slick database driver you have configured in your application.conf file
I have put the following line in config/routes:
GET /evolutions.sql controllers.SchemaEvolutionsController.evolutions
Then I created a controller (app/controllers/SchemaEvolutionsController.scala)
package controllers
import com.google.inject.Inject
import dao.CatDao
import models.HasSchemaDescription
import models.HasSchemaDescription.SqlSchemaDescription
import play.api.Environment
import play.api.mvc.{Action, Controller}
import play.api.Mode
class SchemaEvolutionsController @Inject() (environment: Environment, catDao : CatDao) extends Controller {
def allSchemas : Seq[HasSchemaDescription] = List(catDao) // List all schemas here
def descriptionsForAllSchemas : Seq[SqlSchemaDescription] = allSchemas.map(_.schemaDescription)
def evolutions = Action {
environment.mode match {
case Mode.Prod => NotFound
case _ => Ok(views.txt.evolutions(descriptionsForAllSchemas)).withHeaders(CONTENT_TYPE -> "text/plain")
}
}
}
For this controller there is of course a corresponding view (views/evolutions.scala.txt)
@import models.HasSchemaDescription.SqlSchemaDescription
@(schemaDescriptions : Seq[SqlSchemaDescription])
# Get the newest version of this evolutions script on the address
# http://localhost:9000@(controllers.routes.SchemaEvolutionsController.evolutions)
# when the server runs in development mode
# --- !Ups
@for(
schemaDescription <- schemaDescriptions;
statement <- schemaDescription.createStatements) {
@(statement.replaceAll(";",";;"));
}
# --- !Downs
@for(
schemaDescription <- schemaDescriptions;
statement <- schemaDescription.dropStatements) {
@(statement.replaceAll(";",";;"));
}
For the DAO objects I added a common trait to get the schema description (app/models/HasSchemaDescription):
package models
import models.HasSchemaDescription.SqlSchemaDescription
trait HasSchemaDescription {
def schemaDescription: SqlSchemaDescription
}
object HasSchemaDescription {
type SqlSchemaDescription = slick.profile.SqlProfile#SchemaDescription
}
Now for each DAO object, I must implement the trait and add the DAO to the SchemaEvolutionsController.
For example the DAO for serving cat objects:
class CatDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
extends HasDatabaseConfigProvider[JdbcProfile] with HasSchemaDescription {
import driver.api._
private val Cats = TableQuery[CatsTable]
def schemaDescription : SqlSchemaDescription = Cats.schema
def findById(id : Int) : Future[Option[Cat]] = db.run(Cats.filter(_.id === id).result.headOption)
private class CatsTable(tag: Tag) extends Table[Cat](tag, "CAT") {
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def name = column[String]("NAME")
def color = column[String]("COLOR")
def age = column[Option[Int]]("AGE")
def * = (id, name, color, age) <> (Cat.tupled, Cat.unapply _)
}
}
With this example, you get the following result on http://localhost:9000/evolutions.sql
# Get the newest version of this evolutions script on the address
# http://localhost:9000/evolutions.sql
# when the server runs in development mode
# --- !Ups
create table `CAT` (`ID` INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,`NAME` TEXT NOT NULL,`COLOR` TEXT NOT NULL,`AGE` INTEGER);
# --- !Downs
drop table `CAT`;