Reputation: 2429
I need to make a web service that can will contain lists of objects. One list can contain objects of many types. Here, for example, I have a library of media items. Each item can be either a link or a video, each with their own metadata.
I want to do this with the Lift web framework, because I need something that compiles to WAR and I've used Lift before.
I thought that using MongoDB for this sort of storage would work as, by definition, it's supposed to be able to handle collections of heterogeneous items.
I can define types of BSON objects to be stored in Lift records, but I can't seem to stick away from creating only one type of object in one record/collection. Ideally, I'd like each "thing" (for lack of a better word) in my Library to be either a video or a link. For example:
[
{
"type" : "Video",
"title" : "Story",
"videoID" : "123ab4",
"description": "Feature-length epic",
"time" : 12.6
},
{
"type" : "link",
"url" : "http://www.google.com",
"title": "Search for stuff"
}
]
I should be able to do it with the right type of inheritance, but the way all of the record objects's parents inherit from the object throws me off. Can I get this to work? Having a collection of different things that Lift can use as such?
Here's what I have so far. I haven't tested it, but even if it works what it does is NOT what I want.
import net.liftweb.record._
import net.liftweb.record.field._
import net.liftweb.mongodb._
import net.liftweb.mongodb.record._
import net.liftweb.mongodb.record.field._
class VideoShelf private () extends BsonRecord[VideoShelf] {
def meta = VideoShelf
object title extends StringField (this, 256)
object videoID extends StringField (this, 32 )
object description extends StringField (this, 256)
object time extends DecimalField(this, 0 )
}
object VideoShelf extends VideoShelf with BsonMetaRecord[VideoShelf]
class LinkShelf private () extends BsonRecord[LinkShelf] {
def meta = LinkShelf
object url extends StringField(this, 128)
object title extends StringField(this, 256)
}
object LinkShelf extends LinkShelf with BsonMetaRecord[LinkShelf]
class MediaLibrary private () extends MongoRecord[MediaLibrary] with ObjectIdPk[MediaLibrary] {
def meta = MediaLibrary
///////////////////////////////////////
///////////////////////////////////////
// What I want is this record type to
// contain either of these:
///////////////////////////////////////
object videoshelf extends BsonRecordField(this, VideoShelf)
object linkshelf extends BsonRecordField(this, LinkShelf )
}
object MediaLibrary extends MediaLibrary with MongoMetaRecord[MediaLibrary]
How can I get this?
Upvotes: 1
Views: 354
Reputation: 2429
After seeking more, I found this post: https://groups.google.com/forum/#!topic/liftweb/LmkhvDgrgrI
That led me to this conclusion, which I think is correct, though it has not been tested yet. I may be missing some pieces for it to fully work.
import net.liftweb.record._
import net.liftweb.record.field._
import net.liftweb.mongodb._
import net.liftweb.mongodb.record._
import net.liftweb.mongodb.record.field._
/**
* The base record type for library objects.
*/
trait MediaLibrary[T <: MediaLibrary[T]] extends MongoRecord[T] with ObjectIdPk[T] {
self: T =>
}
/**
* Items in the library that are videos.
*/
class VideoItem extends MediaLibrary[VideoItem] {
def meta = VideoItem
object title extends StringField (this, 256)
object videoID extends StringField (this, 32 )
object description extends StringField (this, 256)
object time extends DecimalField(this, 0 )
}
object VideoItem extends VideoItem with MongoMetaRecord[VideoItem]
/**
* Items in the library that are links.
*/
class LinkItem extends MediaLibrary[LinkItem] {
def meta = LinkItem
object url extends StringField (this, 256)
object title extends StringField (this, 256)
}
object LinkItem extends LinkItem with MongoMetaRecord[LinkItem]
I've also just found out that there is a MongoDB-specific record that's a list of case classes. That seems to be exactly what I need! It's the power of Scala and Mongo being used hand in hand! That's what I wanted from the start. I'll have to try that tomorrow.
Upvotes: 1