Update: I’ve accepted an answer but I’m still very curious why what I tried doesn’t work (to understand Scala implicit behaviors). Any other answers would be greatly appreciated.
(Hopefully this question is answerable without much knowledge of Circumflex, but just in case, here’s the documented source code reference.)
I’m trying to add some convenience functions over the Circumflex ORM library, but I’m running into some barriers trying to use Scala implicit conversions. Below, why doesn’t the implicit conversion trigger? I suspect there’s some complex interaction with the subclassing and/or the recursive type parameters.
import ru.circumflex.orm._
// I subclass Record and Table to add my own convenience methods etc. (not pasted, irrelevant)
abstract class XRecord[PK, R <: XRecord[PK, R]] extends Record[PK, R] { this: R => }
trait XTable[PK, R <: XRecord[PK, R]] extends Table[PK, R] { this: R => }
// Example entity.
class Org extends XRecord[Long,Org] {
val id = "id".BIGINT.NOT_NULL.AUTO_INCREMENT
def PRIMARY_KEY = id
def relation = Org
}
object Org extends Org with XTable[Long,Org]
object Test extends App {
// I want this conversion to work for all Records, not just XRecords.
// Need implicit f to be able to accept XRecord, a subclass of Record.
implicit def toRichRelationNode[PK, R <: Record[PK,R], RR](xs: RR)(implicit f: RR => RelationNode[PK,R]) =
new { def GET(f: RelationNode[PK,R] => Predicate) = 0 }
// This works.
toRichRelationNode(Org) GET (_.id EQ 1)
// This doesn't:
// "No implicit view available from Org.type => ru.circumflex.orm.RelationNode[PK,R]."
Org GET (_.id EQ 1)
}
Frankly, I’ve never used implicit parameters and I’ve never met a condition which forced me to use them (Circumflex itself is written without implicit parameters and goes pretty well as far as I am concerned).
Anyhow, I’ve been able to reproduce your scenario and make it work. It took 2 implicits, however, to make everything go fine. Here’s the code:
Hope it helps.