Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rogue treats EnumField in nested document as String when used in query condition #90

Open
izmailoff opened this issue Sep 5, 2013 · 2 comments

Comments

@izmailoff
Copy link

Hi, I'm using the latest 2.2.0 version and it seems I found a bug. Here is how to reproduce it:

import net.liftweb.mongodb.record.BsonRecord
import net.liftweb.record.field.EnumField
import net.liftweb.mongodb.record.BsonMetaRecord
import net.liftweb.mongodb.record.MongoRecord
import net.liftweb.mongodb.record.field.ObjectIdPk
import net.liftweb.mongodb.record.field.BsonRecordField
import wws.db.connection.MongoConfig
import net.liftweb.mongodb.record.MongoMetaRecord
import com.foursquare.rogue.LiftRogue._

// Enum that "causes throuble"
object TestEnum extends Enumeration {
  type TestEnum = Value
  val ONE, TWO = Value
}

import TestEnum._

// Model classes
class NestedDoc extends BsonRecord[NestedDoc] {
  def meta = NestedDoc
  // the same field type as 'goodField' but Rogue converts it to String in queries
  object thisFieldIsNotAString extends EnumField(this, TestEnum)
}
object NestedDoc extends NestedDoc with BsonMetaRecord[NestedDoc]

class TestDbClass extends MongoRecord[TestDbClass] with ObjectIdPk[TestDbClass] {
  override def meta = TestDbClass
  object goodField extends EnumField(this, TestEnum) // this field works just fine
  object badField extends BsonRecordField(this, NestedDoc)
}
object TestDbClass extends TestDbClass with MongoMetaRecord[TestDbClass] {
  override def mongoIdentifier = MongoConfig.identifier.vend
}

// The app that tests this scenario
object TestDbApp extends App {

  def printDocWithFields(doc: TestDbClass): Unit = {
    println(doc)
    println(doc.goodField.get.getClass)
    println(doc.badField.get.thisFieldIsNotAString.get.getClass)
  }

  MongoConfig.init()

  val doc = TestDbClass.createRecord
    .goodField(ONE)
    .badField(NestedDoc.createRecord.thisFieldIsNotAString(ONE))
  println("\n\nDoc before Save:")
  printDocWithFields(doc)
  val docDb = doc.saveTheRecord().get
  val docId = docDb.id.get
  println("\n\nDoc after Save:")
  printDocWithFields(docDb)

  val query = TestDbClass.where(_.goodField eqs ONE)
    .and(_.badField.subfield(_.thisFieldIsNotAString) eqs TWO)
  println("\n\nQuery:")
  println(query)
  println("Good field type: " + query.asDBObject.get("goodField").getClass)
  println("Bad field type: " +     query.asDBObject.get("badField.thisFieldIsNotAString").getClass)

  val docDbRefetch = TestDbClass.find(docId).head
  println("\n\nDoc fetched with Java driver:")
  printDocWithFields(docDbRefetch)

  val docDbFetchWithRogue = TestDbClass.where(_.id eqs docId)
    .and(_.goodField eqs ONE).fetch().head
  println("\n\nDoc fetched with Rogue using good field:")
  printDocWithFields(docDbFetchWithRogue)

  val docDbFetchWithRogueBadField = TestDbClass.where(_.id eqs docId)
    .and(_.badField.subfield(_.thisFieldIsNotAString) eqs ONE).fetch()
  println("\n\nDoc fetched with Rogue using bad field:")
  docDbFetchWithRogueBadField match {
    case expected :: _ => printDocWithFields(expected) // Desired behavior
    case List() => println("Didn't find the doc!!!") // Current behavior (bug?)
  }
}

I've noticed these comments in src/test/scala/com/foursquare/rogue/EndToEndTest.scala:

// This behavior is broken because we get a String back from mongo, and at
// that point we only have a DummyField for the subfield, and that doesn't
// know how to convert the String to an Enum.

However, this seems to be a different issue, could you confirm?

Thanks

p.s. I can write a test and submit a pull request if it helps.

@izmailoff
Copy link
Author

Output is:

Doc before Save:
class TestDbClass={goodField=ONE, badField=class NestedDoc={thisFieldIsNotAString=ONE}, _id=5227cf8891ce47c497dc3354}
class scala.Enumeration$Val
class scala.Enumeration$Val


Doc after Save:
class TestDbClass={goodField=ONE, badField=class NestedDoc={thisFieldIsNotAString=ONE}, _id=5227cf8891ce47c497dc3354}
class scala.Enumeration$Val
class scala.Enumeration$Val


Query:
db.testdbclasss.find({ "goodField" : 0 , "badField.thisFieldIsNotAString" : "TWO"})
Good field type: class java.lang.Integer
Bad field type: class java.lang.String


Doc fetched with Java driver:
class TestDbClass={goodField=ONE, badField=class NestedDoc={thisFieldIsNotAString=ONE}, _id=5227cf8891ce47c497dc3354}
class scala.Enumeration$Val
class scala.Enumeration$Val


Doc fetched with Rogue using good field:
class TestDbClass={goodField=ONE, badField=class NestedDoc={thisFieldIsNotAString=ONE}, _id=5227cf8891ce47c497dc3354}
class scala.Enumeration$Val
class scala.Enumeration$Val


Doc fetched with Rogue using bad field:
Didn't find the doc!!!

@0xRoch
Copy link

0xRoch commented Nov 24, 2013

I ran into the same issue 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants