iterate over case class data members

Ehud Kaldor picture Ehud Kaldor · Jul 24, 2013 · Viewed 13.6k times · Source

I am writing a play2.1 application with mongodb, and my model object is a bit extensive. when updating an entry in the DB, i need to compare the temp object coming from the form with what's in the DB, so i can build the update query (and log the changes).

i am looking for a way to generically take 2 instances and get a diff of them. iterating over each data member is long, hard-coded and error prone (if a.firstName.equalsIgnoreCase(b.firstName)) so i am looking for a way to iterate over all data members and compare them horizontally (a map of name -> value will do, or a list i can trust to enumerate the data members in the same order every time).

any ideas?

case class Customer(
  id: Option[BSONObjectID] = Some(BSONObjectID.generate),
  firstName: String,
  middleName: String,
  lastName: String,
  address: List[Address],
  phoneNumbers: List[PhoneNumber],
  email: String,
  creationTime: Option[DateTime] = Some(DateTime.now()),
  lastUpdateTime: Option[DateTime] = Some(DateTime.now())
)

all three solutions below are great, but i still cannot get the field's name, right? that means i can log the change, but not what field it affected...

Answer

Eastsun picture Eastsun · Jul 24, 2013

Maybe productIterator is what you wanted:

scala> case class C(x: Int, y: String, z: Char)
defined class C

scala> val c1 = C(1, "2", 'c')
c1: C = C(1,2,c)

scala> c1.productIterator.toList
res1: List[Any] = List(1, 2, c)