Version 0.9.6 of Squeryl introduces a new way to declare classes that have an associated primary key, through the use of the KeyedEntityDef
typeclass. Still the old way to declare
import org.squeryl.KeyedEntity
case class Foo(id: Long, myField: String) extends KeyedEntity[Long]
is supported.
I am trying to migrate an existing application that makes use of Squeryl 0.9.5 to the new version, to make use of custom primitive types, and I am facing a compilation problem. Here is an example of a trait that does not compile anymore
trait Retrievable[A <: KeyedEntity[Long]] {
def table: Table[A]
def get(id: Long): Option[A] = inTransaction {
table.lookup(id)
}
}
It was meant to be used like this:
case class Foo(id: Long, myField: String) extends KeyedEntity[Long]
object Foo extends Retrievable[Foo] {
def table = DB.something
}
...
val foo = Foo.get(235)
Now, when I try to compile, I get the message
The method requires an implicit org.squeryl.KeyedEntityDef[A, Long] in scope, or that it extends the trait KeyedEntity[{K}]
although A
does extend KeyedEntity[Long]
. Even adding an implicit in scope, like
trait Retrievable[A <: KeyedEntity[Long]] {
def table: Table[A]
implicit val ev: <:<[A, KeyedEntity[Long]]
def get(id: Long): Option[A] = inTransaction {
table.lookup(id)
}
}
does not help the implicit resolution, and the trait fails to compile.
Does anyone have a clue why the compiler is not feeding the implicit in the lookup method?
The signature for the lookup method was changed so that it accepts the KeyedEntityDef as an implicit parameter. For backwards compatibility, there is a KeyedEntityDef available for the KeyedEntity type. It's found in QueryDsl (see the kedForKeyedEntities implicit method), and is meant to be imported into scope as part of the "TypeMode" (i.e. PrimitiveTypeMode) that you're using. The quick answer is that you have two choices:
def get(id: Long)(implicit ked: KeyedEntityDef[T,K], dsl: QueryDsl): Option[A]
and then pass them through table.lookup(id)(ked, dsl)
. That will push their resolution off until your get method is called and allow it to be used with whatever custom TypeMode you define.