takezoe/gitbucket — pull request #301 by okapies (2014-03-04 16:50:11+00:00)
Title: Support multiple database driver

### Warning
Currently this PR is **NOT READY TO MERGE** (only for reviewing purpose).

### Objective
Make database driver configurable, other than default [H2Driver](http://slick.typesafe.com/doc/2.0.0/api/scala/slick/driver/H2Driver.html), to support other databases such as [MySQL](http://slick.typesafe.com/doc/2.0.0/api/scala/slick/driver/MySQLDriver.html) and [PostgreSQL](http://slick.typesafe.com/doc/2.0.0/api/scala/slick/driver/PostgresDriver.html).

### Design
Add `Profile` trait to combine it with table, service and controllers.
```
trait Profile {
val profile: ExtendedProfile
}
```

Import `Profile.profile.simple._` instead of `scala.slick.driver.H2Driver.simple._` directly.
```
trait AccountComponent { self: Profile =>
import profile.simple._
object Accounts extends Table[Account]("ACCOUNT") {
def userName = column[String]("USER_NAME", O PrimaryKey)
...
```

Services inherit from corresponding component to import the `Table` object.
```
trait AccountService extends AccountComponent { self: Profile =>
def getAccountByUserName(userName: String, includeRemoved: Boolean = false): Option[Account] =
Query(Accounts) filter(t => (t.userName is userName.bind) && (t.removed is false.bind, !includeRemoved)) firstOption
...
}
```

Now almost every controller requires an `ExtendedProfile` instance to inject into the services, combined with `Profile`.
```
class AccountController(override val profile: ExtendedProfile) extends AccountControllerBase
with AccountService with RepositoryService with ActivityService with OneselfAuthenticator with Profile
```
```
class ScalatraBootstrap extends LifeCycle {
override def init(context: ServletContext) {
val driver = Database.driver(context)
context.mount(new IndexController(driver), "/")
context.mount(new SearchController(driver), "/")
...
```