Skip to content

Commit

Permalink
Fixes discouraged static table object and SlickDDLPlugin when referri…
Browse files Browse the repository at this point in the history
…ng to vals in AutoDDL

* Replace static singleton table objects with vale. From the Slick docs "Also make sure that an actual object for a table is not defined in a static location (i.e. at the top level or nested only inside other objects) because this can cause problems in certain situations due to an overeager optimization performed by scalac. Using a val for your table (with an anonymous structural type or a separate class definition) is fine everywhere." http://slick.typesafe.com/doc/1.0.1/lifted-embedding.html#tables
* SlickDDLPlugin now handles LinkageError, which can happen, when referring to vals in AutoDDL, because it is loaded via reflection.
  • Loading branch information
cvogt committed Jun 28, 2013
1 parent efb6726 commit 74899b4
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 14 deletions.
2 changes: 1 addition & 1 deletion samples/computer-database/app/models/AutoDDL.scala
Expand Up @@ -2,6 +2,6 @@ package play.api.db.slick
object AutoDDL extends AutoDDLInterface{
import models._
def tables = Map(
"default" -> Seq(Companies,Computers)
"default" -> Seq(new Companies,new Computers)
)
}
4 changes: 2 additions & 2 deletions samples/computer-database/app/models/Models.scala
Expand Up @@ -17,7 +17,7 @@ case class Company(id: Option[Long], name: String)

case class Computer(id: Option[Long] = None, name: String, introduced: Option[Date]= None, discontinued: Option[Date]= None, companyId: Option[Long]=None)

object Companies extends Table[Company]("COMPANY") {
class Companies extends Table[Company]("COMPANY") {

def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name", O.NotNull)
Expand Down Expand Up @@ -47,7 +47,7 @@ object Companies extends Table[Company]("COMPANY") {
}
}

object Computers extends Table[Computer]("COMPUTER") {
class Computers extends Table[Computer]("COMPUTER") {

implicit val javaUtilDateTypeMapper = MappedTypeMapper.base[java.util.Date, java.sql.Date](
x => new java.sql.Date(x.getTime),
Expand Down
4 changes: 4 additions & 0 deletions samples/computer-database/app/models/package.scala
@@ -0,0 +1,4 @@
package object models{
val Companies = new Companies
val Computers = new Computers
}
2 changes: 1 addition & 1 deletion samples/play-slick-sample/app/models/AutoDDL.scala
Expand Up @@ -2,6 +2,6 @@ package play.api.db.slick
object AutoDDL extends AutoDDLInterface{
import models._
def tables = Map(
"default" -> Seq(Cats)
"default" -> Seq(new Cats)
)
}
2 changes: 1 addition & 1 deletion samples/play-slick-sample/app/models/Cat.scala
Expand Up @@ -4,7 +4,7 @@ import play.api.db.slick.Config.driver._

case class Cat(name: String, color: String)

object Cats extends Table[Cat]("CAT") {
class Cats extends Table[Cat]("CAT") {

def name = column[String]("name", O.PrimaryKey)
def color = column[String]("color", O.NotNull)
Expand Down
4 changes: 4 additions & 0 deletions samples/play-slick-sample/app/models/package.scala
@@ -0,0 +1,4 @@
package object models{
// Slick table objects should not be static singleton objects, because of a Scala bug. Use vals instead.
val Cats = new Cats
}
32 changes: 23 additions & 9 deletions src/main/scala/play/api/db/slick/SlickPlugin.scala
Expand Up @@ -19,7 +19,7 @@ trait AutoDDLInterface{
class SlickDDLPlugin(app: Application) extends Plugin {
private val CreatedBy = "# --- Created by Slick DDL"
private val configKey = "slick.autoddl_dbs"
def confError(msg:String) = app.configuration.reportError(configKey, msg)
def confError(msg:String,e:Option[Throwable]=None) = app.configuration.reportError(configKey, msg, e)

override def onStart(): Unit = {
app.configuration
Expand Down Expand Up @@ -76,14 +76,28 @@ class SlickDDLPlugin(app: Application) extends Plugin {

/** generates DDL for given datasource */
def evolutionScript(db:String): Option[String] = {
val ddls =
fetchAutoDDLobject
.tables
.get(db)
.map(_.map(_.ddl))
.getOrElse{
throw confError(s"play.api.db.slick.AutoDDL.tables did not contain datasource '$db'")
}
val tables =
try{
fetchAutoDDLobject.tables
} catch {
case e:java.lang.LinkageError =>
throw confError(
s"LinkageError when trying to load play.api.db.slick.AutoDDL.tables via reflection: '$e'."
+" In the definition of play.api.db.slick.AutoDDL.tables you probably referred to a val,"
+" which was not yet initialized. Please refer to defs, singleton objects or alternatively"
+" instantiate the table objects right in the definiton, e.g. like "+"""
def tables = Map(
"default" -> Seq(new MyTableA,new MyTableB)
)"""
, Some(e)
)
}
val ddls = tables
.get(db)
.map(_.map(_.ddl))
.getOrElse{
throw confError(s"play.api.db.slick.AutoDDL.tables did not contain datasource '$db'")
}

val delimiter = ";" //TODO: figure this out by asking the db or have a configuration setting?

Expand Down

0 comments on commit 74899b4

Please sign in to comment.