Jak zaktualizować rekord Mongo przy użyciu Rogue z MongoCaseClassField, gdy klasa przypadku zawiera wyliczenie scala

129

Ja modernizacji istniejącego kodu od Rogue 1.1.8do 2.0.0i lift-mongodb-recordz 2.4-M5 to 2.5.

Mam trudności z pisaniem, MongoCaseClassFieldktóre zawiera wyliczenie ze skalą, z którą naprawdę przydałaby mi się pomoc.

Na przykład,

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

Kiedy próbujemy pisać w tym polu, otrzymujemy następujący błąd:

nie można znaleźć niejawnej wartości parametru dowodowego typu com.foursquare.rogue.BSONType [MyCaseClass] .and (_. myCaseClass setTo myCaseClass)

Kiedyś działało to w Rogue 1.1.8, używając naszej własnej wersji MongoCaseClassField, co sprawiło, że metoda #formats była nadpisywalna. Ale ta funkcja została uwzględniona w rekordzie lift-mongodb w 2.5-RC6, więc pomyśleliśmy, że powinno to teraz działać?

Juneyt Donmez
źródło
9
Wygląda na to, że odpowiedź została udzielona na liście nieuczciwych użytkowników: grokbase.com/t/gg/rogue-users/1367nscf80/…
Asya Kamsky

Odpowiedzi:

7

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

Ale wygodniej jest bezpośrednio tutaj w StackOverFlow:


Przepraszam, powinienem był tu zadzwonić wcześniej.

Jednym z długotrwałych problemów z Rogue było to, że zbyt łatwo było przypadkowo utworzyć pole, którego nie można było serializować jako BSON, i spowodować niepowodzenie w czasie wykonywania (podczas próby dodania tej wartości do obiektu DBObject), a nie w czasie kompilacji .

Wprowadziłem klasę typu BSONType, aby spróbować rozwiązać ten problem. Plusem jest to, że wyłapuje błędy BSON w czasie kompilacji. Wadą jest to, że musisz dokonać wyboru, jeśli chodzi o klasy przypadków.

Jeśli chcesz to zrobić w „prawidłowy” sposób, zdefiniuj swoją klasę sprawy plus „świadek” BSONype dla tej klasy sprawy. Aby zdefiniować świadka BSONType, należy zapewnić serializację z tego typu do typu BSON. Przykład:

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

To powiedziawszy, może to być dość uciążliwe, jeśli robisz to dla każdej klasy sprawy. Drugą opcją jest zdefiniowanie ogólnego monitora, który działa dla dowolnej klasy sprawy, jeśli masz ogólny schemat serializacji:

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

Mam nadzieję że to pomoże,

Valentin Montmirail
źródło