Skip to content

Instantly share code, notes, and snippets.

@etaque
Created November 11, 2016 06:57
Show Gist options
  • Save etaque/87767470c7596dfef5cbf78973bf57cb to your computer and use it in GitHub Desktop.
Save etaque/87767470c7596dfef5cbf78973bf57cb to your computer and use it in GitHub Desktop.
package dao
import scalaz.concurrent.Task
import scalaz.stream.Process
import doobie.imports._
import scalaz._
import Scalaz._
import models.Persisted
trait DoobieDAO[D, M <: Persisted[D]] {
def table: String
def fields: Seq[String]
def fieldsString = fields.map(table ++ "." + _).mkString(", ")
def insertFields = fields.filterNot(_ == "id")
def find(id: Long)(implicit cps: Composite[M]): ConnectionIO[Option[M]] = {
val sql = s"select $fieldsString from $table where id = ?"
HC.process[M](sql, HPS.set((id))).list.map(_.headOption)
}
def get(id: Long)(implicit cps: Composite[M]): ConnectionIO[M] = {
find(id).map(_.getOrElse(sys.error(s"Expected to find id $id in $table")))
}
def list(limit: Int = 20)(implicit cps: Composite[M]): ConnectionIO[List[M]] = {
val sql = s"select $fieldsString from $table limit 20"
HC.process[M](sql, HPS.set(())).list
}
def create(data: D)(implicit dataCps: Composite[D], modelCps: Composite[M]): ConnectionIO[M] = {
val placeholders = (insertFields).map(_ => "?").mkString(", ")
val sql = s"insert into $table (${insertFields.mkString(",")}) values ($placeholders)"
Update[D](sql).withUniqueGeneratedKeys[M](fields: _*)(data)
}
def update(id: Long, data: D)(implicit cps: Composite[D]): ConnectionIO[Int] = {
val placeholders = insertFields.map(f => s"$f = ?").mkString(", ")
val sql = s"update $table set $placeholders where id = ?"
Update[(D, Long)](sql).run((data, id))
}
}
object DoobieDAO {
type ParamValue = (String, Int => PreparedStatementIO[Unit])
def pv[A](name: String)(value: A)(implicit cps: Composite[A]): ParamValue = {
(name, (i: Int) => HPS.set((i, value)))
}
def predicate(paramValues: Seq[ParamValue]): (String, PreparedStatementIO[Unit]) = {
val where = paramValues.map(_._1).mkString(" and ")
val params = paramValues.map(_._2).zipWithIndex.map { case (toParam, i) =>
toParam(i + 1)
}.foldLeft(HPS.set(()))(_ *> _)
(where, params)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment