当case类包含一个scala枚举时,如何使用具有MongoCaseClassField的Rogue更新mongo记录?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (16)

我从升级现有的代码Rogue 1.1.8,以2.0.0lift-mongodb-record2.4-M5 to 2.5

我在编写MongoCaseClassField包含scala枚举时遇到困难,我真的可以使用一些帮助。

例如,

object MyEnum extends Enumeration {
  type MyEnum = Value
  val A = Value(0)
  val B = Value(1)
}

case class MyCaseClass(name: String, value: MyEnum.MyEnum)

class MyMongo extends MongoRecord[MyMongo] with StringPk[MyMongo] {
  def meta = MyMongo

  class MongoCaseClassFieldWithMyEnum[OwnerType <: net.liftweb.record.Record[OwnerType], CaseType](rec : OwnerType)(implicit mf : Manifest[CaseType]) extends MongoCaseClassField[OwnerType, CaseType](rec)(mf) {
    override def formats = super.formats + new EnumSerializer(MyEnum)
  }

  object myCaseClass extends MongoCaseClassFieldWithMyEnum[MyMongo, MyCaseClass](this)
  /// ...
}

当我们尝试写入该字段时,会出现以下错误:

无法找到com.foursquare.rogue.BSONType [MyCaseClass]。和(_. myCaseClass setTo myCaseClass)类型的证据参数的隐式值。

我们曾经在Rogue 1.1.8中使用这个工具,通过使用我们自己的版本MongoCaseClassField,这使得#formats方法可以被覆盖。但是这个功能包含在2.5-RC6的lift-mongodb-record中,所以我们认为这个功能现在应该可以使用了吗?

提问于
用户回答回答于

Rogue长期存在的问题之一是,如果意外地将一个不可序列化为BSON的字段过于容易,并且它在运行时(当您尝试将该值添加到DBObject时)而不是在编译时失败。

我介绍了BSONType类型类来试图解决这个问题。好处是它在编译时捕获BSON错误。缺点是你需要在案例分类时做出选择。

如果你想以这种“正确”的方式来做到这一点,那么定义你的案例类以及针对该案例类的BSONType“见证”。要定义BSONType见证,您需要提供从该类型到BSON类型的序列化。例:

 case class TestCC(v: Int)

 implicit object TestCCIsBSONType extends BSONType[TestCC] {
   override def asBSONObject(v: TestCC): AnyRef = {
     // Create a BSON object
     val ret = new BasicBSONObject
     // Serialize all the fields of the case class
     ret.put("v", v.v)
     ret
   }
 }

也就是说,如果你为每个案例分类做这件事,这可能会非常麻烦。如果你有一个通用的序列化方案,你的第二个选择是定义一个适用于任何案例类的通用证明:

 implicit def CaseClassesAreBSONTypes[CC <: CaseClass]: BSONType[CC] =
new BSONType[CC] {
   override def asBSONObject(v: CC): AnyRef = {
     // your generic serialization code here, maybe involving formats
   }
 }

希望这可以帮助,

扫码关注云+社区