From b239ca89287bf335922c0890f98ffddb41172996 Mon Sep 17 00:00:00 2001 From: Amal Elshihaby Date: Sat, 2 May 2015 23:20:41 +0300 Subject: [PATCH] RIO-115: Handle Reading Reference fields --- .../scala/io/really/model/ReadHandler.scala | 14 ++++---- .../io/really/model/ReadHandlerSpec.scala | 32 ++++++++++++++++++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/modules/really-core/src/main/scala/io/really/model/ReadHandler.scala b/modules/really-core/src/main/scala/io/really/model/ReadHandler.scala index 13e28ac..123ab56 100644 --- a/modules/really-core/src/main/scala/io/really/model/ReadHandler.scala +++ b/modules/really-core/src/main/scala/io/really/model/ReadHandler.scala @@ -114,7 +114,6 @@ class ReadHandler(globals: ReallyGlobals) extends Actor with Stash with ActorLog collection: JSONCollection, cmdOpts: GetOpts): Future[Either[CommandError, GetResult]] = { val requestedFields = getRequestFields(cmdOpts.fields, model) val filter = getFieldsObj(model, requestedFields) - val cursor: Cursor[JsObject] = collection.find(Json.obj("_r" -> r), filter).cursor[JsObject] cursor.headOption map { case Some(doc) if (doc \ "_deleted").asOpt[Boolean].isDefined => @@ -124,10 +123,10 @@ class ReadHandler(globals: ReallyGlobals) extends Actor with Stash with ActorLog val _r = (doc \ "_r").as[R] model.executeOnGet(ctx, globals, doc) match { case Right(plan) => - val itemData = evaluateCalculatedFields(doc, requestedFields, model) + val itemData = evaluateCalculatedFields(doc, availableFields(doc, requestedFields, model), model) Right(GetResult( _r, - addSystemFields(doc, normalizeObject(itemData, requestedFields, plan.hidden)), + addSystemFields(doc, normalizeObject(itemData, availableFields(doc, requestedFields, model), plan.hidden)), accessibleFields(cmdOpts.fields, plan.hidden) )) case Left(terminated) => @@ -214,9 +213,9 @@ class ReadHandler(globals: ReallyGlobals) extends Actor with Stash with ActorLog case doc: JsObject if (doc \ "_deleted").asOpt[Boolean].isEmpty => model.executeOnGet(ctx, globals, doc) match { case Right(plan) => - val itemData = evaluateCalculatedFields(doc, requestedFields, model) + val itemData = evaluateCalculatedFields(doc, availableFields(doc, requestedFields, model), model) Some(ReadItem( - addSystemFields(doc, normalizeObject(itemData, requestedFields, plan.hidden)), + addSystemFields(doc, normalizeObject(itemData, availableFields(doc, requestedFields, model), plan.hidden)), Json.obj("fields" -> accessibleFields(cmdOpts.fields, plan.hidden)) )) case Left(terminated) => None @@ -238,6 +237,9 @@ class ReadHandler(globals: ReallyGlobals) extends Actor with Stash with ActorLog private def getRequestFields(cmdFields: Set[FieldKey], model: Model): Set[FieldKey] = if (cmdFields.isEmpty) model.fields.keySet else cmdFields + private def availableFields(doc: JsObject, requestedFields: Set[FieldKey], model: Model) = + requestedFields.filter(f => model.reactiveFields.get(f).isDefined || (doc \ f).asOpt[JsValue].isDefined) + private def accessibleFields(requested: Set[FieldKey], hidden: Set[FieldKey]) = requested -- hidden private def evaluateCalculatedFields(doc: JsObject, fields: Set[FieldKey], model: Model): JsObject = { @@ -314,7 +316,7 @@ class ReadHandler(globals: ReallyGlobals) extends Actor with Stash with ActorLog case Some(f: CalculatedField[_]) => fieldsObj ++ f.dependsOn.foldLeft(Json.obj()) { case (acc, v) => acc ++ Json.obj(v -> 1) } - //todo handle reference fields + case Some(f: ReferenceField) => fieldsObj ++ Json.obj(field -> 1) case _ => fieldsObj } } diff --git a/modules/really-core/src/test/scala/io/really/model/ReadHandlerSpec.scala b/modules/really-core/src/test/scala/io/really/model/ReadHandlerSpec.scala index b1b6631..0b2701b 100644 --- a/modules/really-core/src/test/scala/io/really/model/ReadHandlerSpec.scala +++ b/modules/really-core/src/test/scala/io/really/model/ReadHandlerSpec.scala @@ -236,6 +236,37 @@ class ReadHandlerSpec extends BaseActorSpecWithMongoDB { ret.body.totalResults shouldBe Some(1) } + it should "return reference fields if requested" in { + val r = R / 'authors / 14 / 'posts + val cmdOpts = ReadOpts( + Set("title", "author"), + EmptyQuery, + 10, + false, + None, + 0, + true, + false + ) + val collection = globals.mongodbConnection.collection[JSONCollection]("posts_authors") + val author = Json.obj("value" -> "authors/14/", "ref" -> Json.obj("_r" -> "authors/14/", "_rev" -> 1, "name" -> "Amal Elshihaby")) + val postObj = Json.obj("title" -> "The post title", "body" -> "The post body", + "_rev" -> 1, "_r" -> r / 112, + "_parent0" -> "authors/14/", "author" -> author, "_id" -> 112) + val result = Await.result(collection.save(postObj), 5.second) + result.ok shouldBe true + globals.readHandler ! Request.Read(ctx, r, cmdOpts, TestProbe().ref) + val ret = expectMsgType[ReadResult] + ret.body.items.size shouldEqual (1) + ret.body.items(0).body shouldEqual Json.obj( + "title" -> "The post title", + "author" -> author, + "_rev" -> 1, "_r" -> r / 112 + ) + ret.body.totalResults shouldBe Some(1) + + } + it should "return calculated fields if requested" in { val r = R / 'cars val query = SimpleQuery(Term("model"), Operator.Eq, TermValue(JsString("KIA"))) @@ -415,7 +446,6 @@ class ReadHandlerSpec extends BaseActorSpecWithMongoDB { "_parent0" -> "authors/15/", "_id" -> 115) val result5 = Await.result(collection.save(postObj5), 5.second) result5.ok shouldBe true - globals.readHandler ! Request.Read(ctx, r, cmdOpts, TestProbe().ref) val ret = expectMsgType[ReadResult] ret.body.items.size shouldEqual (2)