Created
November 11, 2016 06:57
-
-
Save etaque/87767470c7596dfef5cbf78973bf57cb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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