So aktualisieren Sie einen Mongo-Datensatz mithilfe von Rogue mit MongoCaseClassField, wenn die Fallklasse eine Scala-Aufzählung enthält


129

Ich verbessere vorhandenen Code aus Rogue 1.1.8auf 2.0.0und lift-mongodb-recordab 2.4-M5 to 2.5.

Ich habe Schwierigkeiten beim Schreiben MongoCaseClassField, das eine Scala-Aufzählung enthält, bei der ich wirklich Hilfe gebrauchen könnte.

Beispielsweise,

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)
  /// ...
}

Wenn wir versuchen, in dieses Feld zu schreiben, wird der folgende Fehler angezeigt:

Der implizite Wert für den Evidence-Parameter vom Typ com.foursquare.rogue.BSONType [MyCaseClass] .and (_. myCaseClass setTo myCaseClass) konnte nicht gefunden werden.

Früher funktionierte dies in Rogue 1.1.8, indem wir unsere eigene Version von verwendeten MongoCaseClassField, wodurch die Methode #formats überschreibbar wurde. Aber diese Funktion war in 2.5-RC6 in der Lift-Mongodb-Aufzeichnung enthalten, also dachten wir, das sollte jetzt funktionieren?


9
Anscheinend wurde die Antwort auf der Liste der Schurkenbenutzer angegeben: grokbase.com/t/gg/rogue-users/1367nscf80/…
Asya Kamsky

Antworten:


7

Antwort von: http://grokbase.com/t/gg/rogue-users/1367nscf80/how-to-update-a-record-with-mongocaseclassfield-when-case-class-contains-a-scala-enumeration# 20130612woc3x7utvaoacu7tv7lzn4sr2q

Aber bequemer direkt hier auf StackOverFlow:


Entschuldigung, ich hätte mich früher hier einmischen sollen.

Eines der seit langem bestehenden Probleme mit Rogue war, dass es zu einfach war, versehentlich ein Feld zu erstellen, das nicht als BSON serialisierbar war, und dass es zur Laufzeit (wenn Sie versuchen, diesen Wert zu einem DBObject hinzuzufügen) und nicht zur Kompilierungszeit fehlschlug .

Ich habe die Typklasse BSONType eingeführt, um dies zu beheben. Der Vorteil ist, dass BSON-Fehler beim Kompilieren abgefangen werden. Der Nachteil ist, dass Sie eine Auswahl treffen müssen, wenn es um Fallklassen geht.

Wenn Sie dies auf die "richtige" Weise tun möchten, definieren Sie Ihre Fallklasse plus einen BSONType "Zeugen" für diese Fallklasse. Um einen BSONType-Zeugen zu definieren, müssen Sie eine Serialisierung von diesem Typ zu einem BSON-Typ bereitstellen. Beispiel:

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

Dies kann jedoch ziemlich belastend sein, wenn Sie dies für jede Fallklasse tun. Ihre zweite Option besteht darin, einen generischen Zeugen zu definieren, der für jede Fallklasse funktioniert, wenn Sie über ein generisches Serialisierungsschema verfügen:

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

Hoffe das hilft,

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.