(This question is based on a very similar previous request for help. With the introduction of a DAO and multiple database drivers, the same problem requires a different approach, and I hope warrants a new SO question.)
I have a class
and Slick Table
defined like this:
import play.api.db.slick.Profile
case class Foo(title: String, description: String, id: Int = 0)
trait FooComponent extends Profile { this: Profile =>
import profile.simple._
class FooTable(tag: Tag) extends Table[Foo](tag, "FOO") {
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def title = column[String]("TITLE", O.NotNull)
def description = column[String]("DESCRIPTION")
def * = (title, description, id) <> (Foo.tupled, Foo.unapply)
}
}
And a data access object:
class DAO(override val profile: JdbcProfile) extends FooComponent with Profile {
val foos = TableQuery[FooTable]
}
object current {
val dao = new DAO(DB(play.api.Play.current).driver)
}
This is pretty awesome, because now I can add something like the following to my application.conf
:
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.test.driver=org.postgresql.Driver
db.test.user="testuser"
db.test.password=""
db.test.url="jdbc:postgresql:testdb"
... and if I do the following in a Controller:
import models.current.dao._
import models.current.dao.profile.simple._
I have access to my foos
TableQuery
, and it automagically gets the driver and database url given for db.default
in application.conf
.
In a similar, but not-quite-as-nice way, I can do the following in my test Specification
:
"test Foos" in new WithApplication() {
val dao = new DAO(play.api.db.slick.DB("test").driver)
import dao._ //import all our database Tables
import dao.profile.simple._ //import specific database methods
play.api.db.slick.DB("test").withSession { implicit s: Session =>
println(s.conn.getMetaData.getURL)
println(foos.list)
}
However, what if I want to define a method which can act on a TableQuery[Foo]
? Something like this:
def findByTitle(title: String) = foos.filter(_.id === id).list
Problem
What's the correct way of writing the findByTitle
method, and where should I put it so that I can:
- Call it in a way such that it won't collide with a method of the same name which acts on
TableQuery[Bar]
. Coming from OO, I feel like I want to do something likefoos.findByTitle("someFoo")
, but if there's a better way of doing this functional-style, I'm open to suggestions. - Call it from an application Controller such that the query will work with my
db.default
h2 driver, and from my testSpecification
so that it will work with mydb.test
postgres driver.
As an aside, if I can put this in my DAO:
object current {
val dao = new DAO(DB(play.api.Play.current).driver)
}
and then import models.dao.current._
anywhere I want to use this DAO, how can I extend the same form to the following:
object test {
val dao = new DAO(play.api.db.slick.DB("test").driver)
}
If I try to do this, the compiler complains about not having an implicit Application in scope
.