为找不到案例类提供隐式读写器

时间:2017-07-12 18:32:17

标签: scala reactivemongo

我正在尝试使用Reactive Mongo为mongo编写一个很好的通用持久性服务,我正努力为我的记录类子项提供隐式读者/编写器。这是代码。

首先是基础记录类(每个持久记录必须实现它。

abstract class Record {
  val _id: BSONObjectID = BSONObjectID.generate()
}

第二个记录子案例类(非常简单)及其编写器/阅读器(两种可能的方式,Macros与评论中的自定义)

case class TestRecord() extends Record {}
  object TestRecord {
//    implicit object TestRecordWriter extends BSONDocumentWriter[TestRecord] {
//      def write(testRecord: TestRecord): BSONDocument = BSONDocument()
//    }
//
//    implicit object TestRecordReader extends BSONDocumentReader[TestRecord] {
//      def read(doc: BSONDocument): TestRecord = TestRecord()
//    }

    implicit def reader = Macros.reader[TestRecord]
    implicit def writer = Macros.writer[TestRecord]
  }

然后是服务本身

class MongoPersistenceService[R <: Record] @Inject()()
                                                    (implicit ec: ExecutionContext, tag: ClassTag[R]) {

  val collectionName: String = tag.runtimeClass.getSimpleName

  def db: Future[DefaultDB] = MongoConnectionWrapper.getMongoConnection("mongodb://127.0.0.1", "27017")
                              .flatMap(_.database("testDb"))

  def collection: Future[BSONCollection] = db.map(_.collection(collectionName))

  def persist(record: R): Future[Unit] = {
    collection.flatMap(_.insert(record)).map(_ => {})
  }

  def read(id: BSONObjectID): Future[R] = {
    for {
      coll <- collection
      record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
    } yield record
  }
}

这是我失败的测试:

import scala.concurrent.ExecutionContext.Implicits.global

class MongoPersistenceServiceSpec extends WordSpec with Matchers with BeforeAndAfter {
  val persistenceService = new MongoPersistenceService[TestRecord]()

    "persist" when {
      "called" should {
        "succeeds when passing a not persisted record" in {
          val testRecord = TestRecord()

          persistenceService.persist(testRecord)

          val persistedRecord = Await.result(persistenceService.read(testRecord._id), Duration(1000, "millis"))
        assert(persistedRecord.eq(testRecord))
      }
    }
  }
}

编译器抱怨以下消息:

Error:(33, 32) could not find implicit value for parameter writer: reactivemongo.bson.BSONDocumentWriter[R]
  collection.flatMap(_.insert(record)).map(_ => {})

Error:(33, 32) not enough arguments for method insert: (implicit writer: reactivemongo.bson.BSONDocumentWriter[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[reactivemongo.api.commands.WriteResult].
  Unspecified value parameters writer, ec.
    collection.flatMap(_.insert(record)).map(_ => {})

Error:(39, 57) could not find implicit value for parameter reader: reactivemongo.bson.BSONDocumentReader[R]
  record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]

Error:(39, 57) not enough arguments for method one: (implicit reader: reactivemongo.bson.BSONDocumentReader[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[Option[R]].
  Unspecified value parameters reader, ec.
    record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]

任何人都知道我可能会缺少什么? 我还是斯卡拉的新手,所以帮助我在这里找到问题。

我已经尝试编写自定义BSONWriter / BSONReader而不是此处提供的BSONDocumentWriter / BSONDocumentReader但没有成功。

2 个答案:

答案 0 :(得分:2)

简而言之,Scala并不会在整个代码中搜索任何内容。他们需要通过导入,将它们作为参数传递,或者像我在这里建议的那样through a context bound来进入范围:

class MongoPersistenceService[R <: Record : BSONDocumentReader : BSONDocumentWriter]

这是(a)要求在使用特定BSONDocumentReader[R]构造类时可以找到隐式R(和编写者)的一种简写,(b) )将这些含义纳入类的实现范围内,以便隐式传递给insert等其他方法。

为了满足新要求(a),您可能必须在考试中import TestRecord._

答案 1 :(得分:1)

您的persist函数无权访问已定义这些隐式函数的事实。签名应该是这样的:

def persist(record: R)(implicit def writer: BSONDocumentWriter[R]): Future[Unit]

无论你何时调用persist并传递TestRecord,都要确保隐含函数在范围内。

相关问题