novus/salat — Issue #30: SalatDAO persists optional lists differently than required lists
Author: varju
Created: 2012-03-01 21:57:53+00:00
State: open

If a case class has an Option value that contains a List of embedded case class objects, the result stored in Mongo will be different than if the value was not an Option.

Spec that demonstrates the issue:

import com.mongodb.casbah.Imports._
import com.novus.salat.dao._
import com.novus.salat.global._
import org.specs2.mutable._

case class ChildReq(left: String, right: String)
case class ParentReq(child: List[ChildReq], _id: ObjectId = new ObjectId())
object ParentReqDAO extends SalatDAO[ParentReq, ObjectId](MongoConnection()("test")("Parent"))

case class ChildOpt(left: String, right: String)
case class ParentOpt(child: Option[List[ChildOpt]], _id: ObjectId = new ObjectId())
object ParentOptDAO extends SalatDAO[ParentOpt, ObjectId](MongoConnection()("test")("Parent"))

class PersisterTest extends SpecificationWithJUnit {

"mandatory lists of embedded values" should {
"serialize as objects" in {
val parent = ParentReq(List(ChildReq("l1", "r1")))
ParentReqDAO.save(parent)

val loaded = ParentReqDAO.findOneByID(parent._id).get
parent must be equalTo (parent)

val raw = ParentReqDAO.collection.findOneByID(parent._id).get
val child = raw.getAs[BasicDBList]("child").get
val elem = child.getAs[BasicDBObject]("0").get
elem.containsField("left") must be equalTo (true)
elem.containsField("right") must be equalTo (true)
}
}

"optional lists of embedded values" should {
"serialize as objects" in {
val parent = ParentOpt(Some(List(ChildOpt("l1", "r1"))))
ParentOptDAO.save(parent)

val loaded = ParentOptDAO.findOneByID(parent._id).get
parent must be equalTo (parent)

val raw = ParentOptDAO.collection.findOneByID(parent._id).get
val child = raw.getAs[BasicDBList]("child").get
val elem = child.getAs[BasicDBObject]("0").get
elem.containsField("left") must be equalTo (true)
elem.containsField("right") must be equalTo (true)
}
}
}