Case class hierarchies in lift-mongodb-record

65 views
Skip to first unread message

Nolan Darilek

unread,
Aug 11, 2010, 11:41:56 AM8/11/10
to Lift list
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'm trying and failing to do something like the following:

trait AppointmentStatus extends JsonObject[AppointmentStatus] {

def meta = AppointmentStatus

}

object AppointmentStatus extends JsonObjectMeta[AppointmentStatus]

case object Accepted extends AppointmentStatus
case class Deferred(reason:String) extends AppointmentStatus
case object Pending extends AppointmentStatus
case class Rejected(reason:String) extends AppointmentStatus

...
class Appointment extends MongoRecord[Appointment] with Model[Appointment] {
...
object status extends JsonObjectField[Appointment,
AppointmentStatus](this, AppointmentStatus) {
def defaultValue = Pending
}

}

First, is this type of thing even possible? Or should I store the status
as a String and override the field's apply() method to serialize case
classes somehow?

Assuming it is possible, what needs to happen to make this work? At the
moment, I get a blank JSON object in my status field regardless of what
I manually set.

Does each status need a meta object? If so, how does that work in
instances where I'm using case objects? Or does everything need to be a
case class?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkxixMQACgkQIaMjFWMehWL8/QCfZ/KF8nd5VhVZHO+GD2cJ2qQU
wg4Ani6CQ5rfbFz5eUI83zchXlPijc9R
=QEH5
-----END PGP SIGNATURE-----

Tim Nelson

unread,
Aug 11, 2010, 12:08:17 PM8/11/10
to lif...@googlegroups.com
I don't think that's possible. JsonObject uses lift-json to transform
the case class into a JValue. In this case it's looking at the
AppointmentStatus trait and not finding any members. That's why it's
always blank.

I'm not sure how this could be supported, what would the case objects
values be when saved? The other 2 case classes would only have the
reason saved, since it's the only member.

Tim

> --
> You received this message because you are subscribed to the Google Groups "Lift" group.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
>
>

Nolan Darilek

unread,
Aug 11, 2010, 12:38:27 PM8/11/10
to lif...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello.

I'm not sure that I expected the values to be anything in particular, or
even expected it to work at all. I just thought that it might, or that
there might be some idiom for doing this.

I've changed mycode to the following:

abstract class AppointmentStatus(status:String, reason:Option[String])
extends JsonObject[AppointmentStatus] {

def meta = AppointmentStatus

}

object AppointmentStatus extends JsonObjectMeta[AppointmentStatus]

case object Accepted extends AppointmentStatus("accepted", None)
case class Deferred(reason:String) extends AppointmentStatus("deferred",
Some(reason))
case object Pending extends AppointmentStatus("pending", None)
case class Rejected(reason:String) extends AppointmentStatus("rejected",
Some(reason))

Now if I do something like:

appointment.is.status(Deferred("Pending"))

I get a status that looks like:

{"reason": "Pending"}

Does it not look into the superclass when retrieving values? I'd have
expected {"status": "deferred", "reason": "Pending"}

I changed the abstract class such that status and reason were vals, but
this doesn't work either. I also changed the parameter name in the
subclasses to r:String and see that it is being serialized as "r":,
which seems to indicate that I'm on the wrong track with this. So is
there a better way, or am I stuck serializing and matching against
strings like "pending", "accepted", etc.? If so then I'll make due, but
I'd feel pretty silly if there was another way and I missed it. :)

- --


You received this message because you are subscribed to the Google
Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to
liftweb+u...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/liftweb?hl=en.
>>
>>

-----BEGIN PGP SIGNATURE-----


Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkxi0gMACgkQIaMjFWMehWIN4ACfdAvsOQxvNE6YdNjTYDv6ER29
mG0AmwQH2QIoj4S+GkiSdrJ6mMtjKnQG
=QVK4
-----END PGP SIGNATURE-----

Tim Nelson

unread,
Aug 11, 2010, 3:58:40 PM8/11/10
to lif...@googlegroups.com
This is actually more of a lift-json question, so Joni might be able
to give you a better answer, but I don't believe this will work
either. It sure would be nice if it did though.

JsonObject uses Extraction to transform case classes to JValues and
back. So, if lift-json can support this then it will work.

Tim

Nolan Darilek

unread,
Aug 11, 2010, 4:14:18 PM8/11/10
to Lift list
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Here's what I ended up doing. It's not a bad solution, and seems to work.

abstract class AppointmentStatus(statusType:String) {
def toMap = Map("type" -> statusType)
}

case object Accepted extends AppointmentStatus("accepted")
case object Pending extends AppointmentStatus("pending")

abstract class AppointmentStatusWithReason(statusType:String,
reason:String) extends AppointmentStatus(statusType) {
override def toMap = super.toMap++Map("reason" -> reason)
}

case class Deferred(reason:String) extends

AppointmentStatusWithReason("deferred", reason)


case class Rejected(reason:String) extends

AppointmentStatusWithReason("rejected", reason)

class Appointment extends MongoRecord[Appointment] with Model[Appointment] {

object appointmentStatus extends MongoMapField[Appointment,
String](this) {
override def name = "status"
override def defaultValue = Map("type" -> "pending")
}

def status_=(s:AppointmentStatus) = appointmentStatus(s.toMap)

def status:AppointmentStatus = appointmentStatus.value("type") match {
case "accepted" => Accepted
case "pending" => Pending
case "deferred" => Deferred(appointmentStatus.value("reason"))
case "rejected" => Rejected(appointmentStatus.value("reason"))
}

}

iEYEARECAAYFAkxjBJkACgkQIaMjFWMehWJmlQCeNKSJ6uwhxwJF5trLaadhlaD6
r9kAn1YGkg9QGOeD2ar5HXF87NcjpbEE
=jcdX
-----END PGP SIGNATURE-----

Erik Allik

unread,
Apr 15, 2014, 10:22:34 AM4/15/14
to lif...@googlegroups.com
Should MongoCaseClassField be considered as the answer to this question as of today?

Tim Nelson

unread,
Apr 15, 2014, 7:10:39 PM4/15/14
to lif...@googlegroups.com
I don't believe lift-json can serialize case objects, so no, that would not work here.
Reply all
Reply to author
Forward
0 new messages