如何使用Rogue和MongoCaseClassField更新包含Scala枚举的案例类中的Mongo记录

130

我正在将现有代码从 Rogue 1.1.8 升级到 2.0.0,同时将 lift-mongodb-record2.4-M5 升级到 2.5

我在编写包含 Scala 枚举的 MongoCaseClassField 方面遇到了一些困难,真的需要一些帮助。

例如,

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] 的证明参数 .and(_.myCaseClass setTo myCaseClass)

在 Rogue 1.1.8 中,我们使用自己版本的 MongoCaseClassField,使 #formats 方法可重写,以前他是管用的。但此功能已经包含在 lift-mongodb-record 中 2.5-RC6 版本中,所以现在应该可以使用吗?


9
看起来答案已经在“rogue-users”列表上提供了:http://grokbase.com/t/gg/rogue-users/1367nscf80/how-to-update-a-record-with-mongocaseclassfield-when-case-class-contains-a-scala-enumeration#20130612woc3x7utvaoacu7tv7lzn4sr2q - Asya Kamsky
1个回答

7

来自以下网址的回答:http://grokbase.com/t/gg/rogue-users/1367nscf80/how-to-update-a-record-with-mongocaseclassfield-when-case-class-contains-a-scala-enumeration#20130612woc3x7utvaoacu7tv7lzn4sr2q

但在 StackOverflow 上直接查看更方便:


对不起,我应该早点加入这里。

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
   }
 }

说到这里,如果你为每个案例类都做这件事情,那么这将会是非常繁琐的。你的第二个选择是定义一个通用的witness,适用于任何案例类,如果你有一个通用的序列化方案:
 implicit def CaseClassesAreBSONTypes[CC <: CaseClass]: BSONType[CC] =
new BSONType[CC] {
   override def asBSONObject(v: CC): AnyRef = {
     // your generic serialization code here, maybe involving formats
   }
 }

希望这能帮到你,

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接