130 votes

Comment mettre à jour un enregistrement mongo en utilisant Rogue avec MongoCaseClassField lorsque la classe de cas contient une énumération scala.

Je mets à jour le code existant de Rogue 1.1.8 a 2.0.0 y lift-mongodb-record de 2.4-M5 to 2.5 .

J'ai des difficultés à écrire MongoCaseClassField qui contient un enum en scala, pour lequel j'aurais vraiment besoin 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 une valeur implicite pour le paramètre de preuve de type com.foursquare.rogue.BSONType[MyCaseClass] .and(_.myCaseClass setTo myCaseClass)

Nous avions l'habitude de faire fonctionner cette fonction dans Rogue 1.1.8, en utilisant notre propre version de l'outil d'évaluation de l'impact sur l'environnement. MongoCaseClassField qui a rendu la méthode #formats surchargeable. Mais cette fonctionnalité a été incluse dans lift-mongodb-record dans la version 2.5-RC6, alors nous avons pensé que cela devrait fonctionner maintenant ?

7voto

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 plus tôt.

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

J'ai introduit la classe de type BSONType pour tenter de résoudre ce problème. L'avantage est que qu'elle permet de détecter les erreurs BSON à la compilation. L'inconvénient est que vous devez faire un choix lorsqu'il s'agit de classes de cas.

Si vous voulez procéder de la manière "correcte", définissez votre classe de cas plus un témoin" de type BSONT pour cette classe de cas. Pour définir un témoin de type BSONT, vous devez fournir une sérialisation de ce type vers 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 cas classe. Votre deuxième option est de définir un témoin générique qui fonctionne pour n'importe quelle classe de cas. classe de cas, si vous disposez d'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 vous aidera,

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X