Search code examples
scalaplayframeworkslickplay-slick

Easy way to generate 1.sql from model?


As a Slick noob I do not understand why I have to specify my model twice, first in Scala and then in 1.sql to create the tables. That does not look DRY. Is there an easy way to generate 1.sql (and 2..n.sql) from the model during development?


Solution

  • I created my own sbt task to easily generate the 1.sql from model using the code generation:

    in build.sbt file:

    val generate_schema = taskKey[Unit]("Schema Generator")
    
    generate_schema <<= (fullClasspath in Runtime) map {classpath =>
        val loader: ClassLoader = ClasspathUtilities.toLoader(classpath.map(_.data).map(_.getAbsoluteFile))
        val schemaGenerator = loader.loadClass("misc.SchemaGenerator").newInstance().asInstanceOf[Runnable]
        schemaGenerator.run
    }
    

    the misc.SchemaGenerator class:

    package misc
    
    import models.Article
    import models.Category
    import play.api.Logger
    import slick.driver.PostgresDriver.api._
    import scala.concurrent._
    import ExecutionContext.Implicits.global
    import scala.reflect.io.File
    
    class SchemaGenerator extends Runnable {
    
      def run = {
        println("---------------------GENERATING SCHEMA.....")
        val categories = TableQuery[Category]
        val articles = TableQuery[Article]
    
        val file = File("/home/pedro/NetBeansProjects/play-scala-angular-sample/my-blog-server/conf/evolutions/default/1.sql")
    
        val sb = new StringBuilder("# --- !Ups  \n\n")
        categories.schema.create.statements.foreach(st => sb.append(st.toString + ";\n"))
        sb.append("\n\n")
        articles.schema.create.statements.foreach(st => sb.append(st.toString + ";\n"))
    
        sb.append("\n\n")
        sb.append("# --- !Downs")
        sb.append("\n\n")
    
        categories.schema.drop.statements.foreach(st => sb.append(st.toString + ";\n"))
        sb.append("\n\n")
        articles.schema.drop.statements.foreach(st => sb.append(st.toString + ";\n"))
    
    //    Logger.info("value: [" + sb + "] sb")
        file.writeAll(sb.toString)
        Logger.info("----------------------FINISHED GENERATING SCHEMA--------------------------")
      }
    
    }
    

    You can execute the task from the activator console: generate_schema.

    Hope it helps.