Bagaimana cara memperbarui catatan mongo menggunakan Rogue dengan MongoCaseClassField ketika kelas kasus berisi enumerasi scala

129

Saya memutakhirkan kode yang ada dari Rogue 1.1.8ke 2.0.0dan lift-mongodb-recorddari 2.4-M5 to 2.5.

Saya mengalami kesulitan menulis MongoCaseClassFieldyang berisi scala enum, yang benar-benar dapat saya bantu.

Sebagai contoh,

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

Ketika kami mencoba menulis ke bidang ini, kami mendapatkan kesalahan berikut:

tidak dapat menemukan nilai implisit untuk parameter bukti dari tipe com.foursquare.rogue.BSONType [MyCaseClass] .and (_. myCaseClass setTo myCaseClass)

Kami dulu memiliki ini berfungsi di Rogue 1.1.8, dengan menggunakan versi kami sendiri MongoCaseClassField, yang membuat metode #format ditimpa. Tapi fitur itu dimasukkan ke dalam lift-mongodb-record di 2.5-RC6, jadi kami pikir ini seharusnya hanya berfungsi sekarang?

Juneyt Donmez
sumber
9
Sepertinya jawabannya diberikan pada daftar pengguna nakal: grokbase.com/t/gg/rogue-users/1367nscf80/…
Asya Kamsky

Jawaban:

7

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

Tetapi lebih nyaman langsung di sini di StackOverFlow:


Maaf, saya seharusnya berdentang di sini lebih cepat.

Salah satu masalah lama dengan Rogue adalah bahwa terlalu mudah untuk secara tidak sengaja membuat bidang yang tidak dapat diserialisasi seperti BSON, dan gagal saat runtime (ketika Anda mencoba menambahkan nilai itu ke DBObject) daripada pada waktu kompilasi .

Saya memperkenalkan kelas tipe BSONType untuk mencoba mengatasi ini. Keuntungannya adalah menangkap kesalahan BSON pada waktu kompilasi. Kelemahannya adalah Anda harus membuat pilihan ketika datang ke kelas kasus.

Jika Anda ingin melakukan ini dengan cara "benar", tentukan kelas kasus Anda ditambah "saksi" BSONType untuk kelas kasus itu. Untuk mendefinisikan saksi tipe BSON, Anda harus memberikan serialisasi dari tipe itu ke tipe BSON. Contoh:

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

Yang mengatakan, ini bisa sangat memberatkan jika Anda melakukannya untuk setiap kelas kasus. Opsi kedua Anda adalah menentukan saksi generik yang berfungsi untuk kelas kasus apa pun, jika Anda memiliki skema serialisasi generik:

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

Semoga ini membantu,

Valentin Montmirail
sumber