views:

515

answers:

1

Hi all-

I am creating a website which will need two types of users: students and providers. In a traditional java setting I would create a user class (or interface) and then create two classes which inherited from the user. Is this the best course in scala too, using the "extends" and "with" modifiers? If that is indeed the best way (which I suspect it is), what the best way to map this in the DB? Would it be best to keep a "type" column and then have it set to one or the other?

The second question is how to work with the view. The display will be very different depending on which type of user one is and so I figure there will be some serious routing logic involved or at least logic built into snippets in the view.

I guess the overarching question is: Is there a "preferred" way to go about doing this (like a recipe in rails or some such), or am I kind of out on my own?

Thanks

+6  A: 

If that is indeed the best way (which I suspect it is), what the best way to map this in the DB? Would it be best to keep a "type" column and then have it set to one or the other?

I don't think there is clear "the best way" to design database structure given a scenario. The text book answer is database normalization and DRY.

Three tables approach

One way for instance could be to create User table containing both types of users, storing only the common attributes, and create Student table and Provider table with foreign key to User table and specialized attributes if any. This probably is not what a traditional relational database person would recommend, but it maps closer to the OO inheritance model.

One table approach

Another approach like you said would be to just create a "UserType" field and store both types of users into User table. It's simple, but you then miss the opportunity to take advantage of the referential integrity of the relational database. For example, if you were to create child table specific only to Student, such as Homework, you can't simply make foreign key to StudentID if both students and providers lived in User table.

Two tables approach

If you are using Object-Relational Mapping framework, likely the easiest way to go is to map exactly what you want in the object world strait into the database, which would be having Student table and Provider table, and express the commonality of two as trait in Scala side.

I found Lift cheat sheet:

Defining Models

lift O-R mapped models are defined based on a class with fields.

class WikiEntry extends KeyedMapper[Long, WikiEntry] {
  def getSingleton = WikiEntry // what's the "meta" object
  def primaryKeyField = id

  // the primary key
  object id extends MappedLongIndex(this)

  // the name of the entry
  object name extends MappedString(this, 32) {
    override def dbIndexed_? = true // indexed in the DB
  }

  object owner extends MappedLongForeignKey(this, User)

  // the text of the entry
  object entry extends MappedTextarea(this, 8192) {
    override def textareaRows  = 10
    override def textareaCols = 50
  }
}

Discussion on having shared base traits for Models.

In the thread David Pollak writes:

You're looking for some Scala magic:

trait Posting[MyType <: Mapper[MyType]] { // Defines some common fields for posted user content 
  self: MyType => 
  def primaryKeyField = id 
  object id extends MappedLongIndex(this) 
  object creator extends MappedLongForeignKey(this, User) 
  object createdAt extends MappedLong(this) { 
    override def defaultValue = System.currentTimeMillis 
  } 
} 

class FooPosting extends KeyedMapper[FooPosting] with Posting[MyType]
eed3si9n
Thanks, this has been pretty helpful. However, the user object is fairly complicated (as it extends metamegaprotouser etc.) is there any way to transfer all that functionality into a trait? Also, assuming I want both students and providers to have an attached profile class, how would I write the class to check for the user trait? Thanks
@Dave, see the last part of my post on shared base traits for Models, esp the quoted code. 1. trait Posting[MyType <: Mapper[MyType]]. 2. object creator extends MappedLongForeignKey(this, User).
eed3si9n