Comment mettre à jour un enregistrement mongo à l'aide de Rogue avec MongoCaseClassField lorsque la classe de cas contient une énumération scala


129

Je suis mise à niveau du code existant de Rogue 1.1.8à 2.0.0et à lift-mongodb-recordpartir 2.4-M5 to 2.5.

J'ai des difficultés à écrire MongoCaseClassFieldqui contient une énumération scala, avec laquelle je pourrais vraiment utiliser un peu d'aide.

Par exemple,

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

Lorsque nous essayons d'écrire dans ce champ, nous obtenons l'erreur suivante:

impossible de trouver la valeur implicite du paramètre de preuve de type com.foursquare.rogue.BSONType [MyCaseClass] .and (_. myCaseClass setTo myCaseClass)

Nous avions l'habitude de faire fonctionner cela dans Rogue 1.1.8, en utilisant notre propre version de MongoCaseClassField, ce qui rendait la méthode #formats remplaçable. Mais cette fonctionnalité a été incluse dans lift-mongodb-record dans 2.5-RC6, nous avons donc pensé que cela devrait fonctionner maintenant?


9
On dirait que la réponse a été fournie sur la liste des utilisateurs malhonnêtes
Asya Kamsky

Réponses:


7

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

Mais plus pratique directement ici sur StackOverFlow:


Désolé, j'aurais dû intervenir ici plus tôt.

L'un des problèmes de longue date avec Rogue était qu'il était trop facile de créer accidentellement un champ qui n'était pas sérialisable en tant que BSON, et de le faire échouer à l'exécution (lorsque vous essayez d'ajouter cette valeur à un DBObject) plutôt qu'au moment de la compilation. .

J'ai introduit la classe de type BSONType pour essayer de résoudre ce problème. L'avantage est qu'il détecte les erreurs BSON au moment de la compilation. L'inconvénient est que vous devez faire un choix en ce qui concerne les classes de cas.

Si vous voulez faire cela de la manière «correcte», définissez votre classe de cas plus un «témoin» BSONType pour cette classe de cas. Pour définir un témoin BSONType, vous devez fournir une sérialisation de ce type à un type BSON. Exemple:

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

Cela dit, cela peut être assez fastidieux si vous le faites pour chaque classe de cas. Votre deuxième option consiste à définir un témoin générique qui fonctionne pour n'importe quelle classe de cas, si vous avez un schéma de sérialisation générique:

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

J'espère que cela t'aides,

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.