Como atualizar um registro mongo usando Rogue com MongoCaseClassField quando a classe case contém uma enumeração scala

129

Eu estou atualizando o código existente a partir Rogue 1.1.8de 2.0.0e lift-mongodb-recordpartir 2.4-M5 to 2.5.

Estou tendo dificuldade em escrever MongoCaseClassFieldque contenha um scala enum, com o qual eu realmente poderia usar alguma ajuda.

Por exemplo,

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

Quando tentamos gravar neste campo, obtemos o seguinte erro:

não foi possível encontrar um valor implícito para o parâmetro de evidência do tipo com.foursquare.rogue.BSONType [MyCaseClass] .and (_. myCaseClass setTo myCaseClass)

Costumávamos ter isso funcionando no Rogue 1.1.8, usando nossa própria versão do MongoCaseClassField, o que tornava o método #formats substituível. Mas esse recurso foi incluído no lift-mongodb-record no 2.5-RC6, então achamos que isso deveria funcionar agora?

Juneyt Donmez
fonte
9
Parece que a resposta foi fornecida na lista de usuários não autorizados
Asya Kamsky

Respostas:

7

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

Mas mais conveniente diretamente aqui no StackOverFlow:


Desculpe, eu deveria ter entrado aqui mais cedo.

Um dos problemas de longa data com o Rogue era que era muito fácil criar acidentalmente um campo que não era serializável como BSON e falhar no tempo de execução (quando você tenta adicionar esse valor a um objeto DBO) em vez de no tempo de compilação .

Eu introduzi a classe de tipo BSONType para tentar resolver isso. A vantagem é que ele pega erros BSON em tempo de compilação. A desvantagem é que você precisa fazer uma escolha quando se trata de aulas de caso.

Se você deseja fazer isso da maneira "correta", defina sua classe de caso mais uma "testemunha" BSONType para essa classe de caso. Para definir uma testemunha BSONType, você precisa fornecer serialização desse tipo para um tipo BSON. Exemplo:

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

Dito isto, isso pode ser bastante oneroso se você estiver fazendo isso para cada classe de caso. Sua segunda opção é definir uma testemunha genérica que funcione para qualquer classe de caso, se você tiver um esquema de serialização genérico:

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

Espero que isto ajude,

Valentin Montmirail
fonte