Skip to content

Instantly share code, notes, and snippets.

@mathieuancelin
Last active August 29, 2015 14:00
Show Gist options
  • Save mathieuancelin/11284292 to your computer and use it in GitHub Desktop.
Save mathieuancelin/11284292 to your computer and use it in GitHub Desktop.
package fwk
import scala.concurrent.{Future, ExecutionContext}
import play.api.libs.json.{JsUndefined, Json, JsObject, Format}
import play.modules.reactivemongo.json.collection.JSONCollection
import reactivemongo.bson.BSONObjectID
import reactivemongo.core.commands.LastError
import play.modules.reactivemongo.ReactiveMongoPlugin
import play.modules.reactivemongo.json.BSONFormats._
trait GenericCollection[T, Id, Error] {
def insert(t: T)(implicit ctx: ExecutionContext): Future[(Id, Error)]
def delete(id: Id)(implicit ctx: ExecutionContext): Future[Error]
def update(id: Id, t: T)(implicit ctx: ExecutionContext): Future[Error]
def get(id: Id)(implicit ctx: ExecutionContext): Future[Option[(T, Id)]]
def findAll()(implicit ctx: ExecutionContext): Future[Traversable[(T, Id)]] = find(Json.obj())(ctx)
def find(sel: JsObject)(implicit ctx: ExecutionContext): Future[Traversable[(T, Id)]]
def findOne(sel: JsObject)(implicit ctx: ExecutionContext): Future[Option[(T, Id)]]
}
abstract class GenericMongoCollection[T](implicit format: Format[T]) extends GenericCollection[T, BSONObjectID, LastError] {
def coll: JSONCollection
override def insert(t: T)(implicit ctx: ExecutionContext): Future[(BSONObjectID, LastError)] = {
val id = BSONObjectID.generate
val obj = format.writes(t).as[JsObject]
obj \ "_id" match {
case _:JsUndefined => coll.insert(obj ++ Json.obj("_id" -> id)).map(err => (id, err))
case _ => coll.insert(obj).map(err => (id, err))
}
}
override def delete(id: BSONObjectID)(implicit ctx: ExecutionContext): Future[LastError] = {
coll.remove(Json.obj("_id" -> id))
}
override def update(id: BSONObjectID, t: T)(implicit ctx: ExecutionContext): Future[LastError] = {
coll.update(
Json.obj("_id" -> id),
Json.obj("$set" -> t)
)
}
override def get(id: BSONObjectID)(implicit ctx: ExecutionContext): Future[Option[(T, BSONObjectID)]] = {
coll.find(Json.obj("_id" -> id)).cursor[JsObject].headOption.map(_.map( js => (js.as[T], id)))
}
override def findAll()(implicit ctx: ExecutionContext): Future[Traversable[(T, BSONObjectID)]] = find(Json.obj())(ctx)
override def find(sel: JsObject)(implicit ctx: ExecutionContext): Future[Traversable[(T, BSONObjectID)]] = {
coll.find(sel).cursor[JsObject].collect[Traversable]().map(_.map(item => (item.as[T], (item \ "_id").as[BSONObjectID])))
}
override def findOne(sel: JsObject)(implicit ctx: ExecutionContext): Future[Option[(T, BSONObjectID)]] = {
coll.find(sel).one[JsObject].map(_.map(item => (item.as[T], (item \ "_id").as[BSONObjectID])))
}
}
class GenericMongoCrud[T](c: JSONCollection)(implicit format: Format[T]) extends GenericMongoCollection[T] {
override def coll: JSONCollection = c
}
package object models {
case class Person(name: String, surname: String, age: Int)
object Person {
implicit val fmt = Json.format[Person]
}
}
package object repositories {
import models.Person
import models.Person._
object MyMongoColl extends GenericMongoCollection[Person] {
override def coll: JSONCollection = ReactiveMongoPlugin.db(play.api.Play.current).collection[JSONCollection]("truc")
}
object MyMongoRepo {
lazy val crud = new GenericMongoCrud[Person](ReactiveMongoPlugin.db(play.api.Play.current).collection[JSONCollection]("truc"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment