SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Member
    Join Date
    Jun 2008
    Posts
    10
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Question about models and routing

    Hi,

    I'm a bit stuck with how to setup a specific scenario...

    My app has three types of users, 2 of which hold unique attributes and the third being general that has attributes common to all. I've been thinking that I could have 3 tables (users, user_type1, and user_type2). I'm stuck on how to model this however though... do my user_type#s really[I]belong_to[I] users? Logically they are users, but with augmented data of one type or another...

    in terms of routes, if I use belongs to and nest them I'd end up with /users/user_type#/id and that's not how I'm thinking either.

    I was thinkiing having 3 tables would be the dry way to do this but my other thought was to have one user table with all the options and simply show the appropriate ones to the selected user_type... then add a binary field to identify the user_type in the database... ie null = general, 0 = user_type1, and 1 = user_type2.

    Completely confused. Any thoughts?

    Thanks

  2. #2
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not the person to ask about routing - I tend to use the most basic out of the box routing.

    I'd be very surprised if having three different user tables would be the best solution. If being a user has a set of properties that are common to all three user types, then they probably need to be together.

    How far you split out the separate material depends on how big the differences are. I suggest there are four levels (from 1 being the least different from a single user definition, to 4 being the most different):
    1. All you want to do is distinguish between users of different types. For this you just want either a user_type field or a field specific to the property that identifies each user type. A simple example being male or female where you would add a gender field.
    2. You wish to record a small number (I'd limit this to 3 or 4) of properties that appear for some user types. Add fields for these small number of properties. For example, to record whether they are a qualified first-aider, or have had manual handling training. Those users that don't would have NULLs in these fields.
    3. Being a user of a particular type adds a special set of properties (not just one or two). This can be handled by adding a new model. For example, a 'Role' model. The Role model holds the extra properties. This really comes into its own when multiple users have the same role. In this situation, you would have one Role definition and many users pointing at that via a role_id field and a has_many/belongs_to relationship. Then you can do things like look at role.users, which would be an array of users who share a particular role. It also wouldn't be difficult to slot a join table between roles and users, and use a has_and_belongs_to_many relationship. This would allow any user to have multiple roles.
    4. The last case is when there are very few properties that are shared by the different types of user. In fact they aren't different types of one object - they a separate objects with small similarities or shared properties. In this case you would need three models, with perhaps a shared forth model that held their shared properties

  3. #3
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Check out single table inheritance. It's built into Rails for exactly this type of situation.

  4. #4
    SitePoint Member
    Join Date
    Jun 2008
    Posts
    10
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the responses - I checked out STI in The Rails Way and noted it specifically warns of ReggieB's #2 - too many differences.

    I guess this is where I go into some more detail.

    This analogy might be a little crass, but it actually fits the relationship of my model really well...

    There are pretty much two types of users with differing functions as opposed to hierarchical privileges. One type presents objects and the other requests them. Lets say they're Pimps and Johns(I am NOT making this app)... The pimps have hookers and the Johns request them. Aside from the basic user data used for authentication, they don't really share much common data... (in my app, the two types share about 5 additional fields and differ on 12 - can assume 6 for one and 6 for the other). In the analogy, Johns might be required to enter an address to receive the hookers while pimps obviously would not.

    In the app, the two do totally different things... there's no type one can do A but not B and C while type 2 can do whatever. Here, besides viewing the two user type only interact through the one way request from John to Pimp.

    In terms of Roles and Rights, they don't really overlap, except that it's concievable that a Pimp is a John too... but having that ability is not at all critical.

    My early concern was dealing with the form... I wanted to just have a toggle that displays the appropriate form fields.

    But I'm thinking that the STI method is overkill and that it might just be easier to have a model for each type that allows them to do their separate functions and have extra database tables to contain the type_specific data. Then I'd just have to figure out how to toggle half the form or make a two staged form entry.

    @ReggieB, the ref. wiki.rubyonrails... is 503 right now.

    I'm using Restful-Authentication and it leverages a user table and model so I figure I can't easily just dump the common user model and just have type_A and Type_B without the generic user setup.

    Thanks for the comments

  5. #5
    SitePoint Member
    Join Date
    Jul 2008
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm...I'm not completely sure, but STI in The Rails Way is probably the best resource. I'll try to find out the answer to your question, but I'm not sure I know.

  6. #6
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could make two tables named johns and pimps. Put the john specific attributes in the johns table and pimp specific attributes in the pimps table.

    Code:
    User belongs_to :role, :polymorphic => true
    John has_one :user, :as => :role
    Pimp has_one :user, :as => :role
    I know this sounds weird (e.g. John doesn't have a user). Think about it in plain old objects terms. We have a User class that has an attribute called `role`. The role attribute can either be an instance of class John or an instance of class Pimp, depending on what the user is. The John class can have an attribute credit_card_number, and the Pimp class has phone_number.

    With this set up you can do:

    Code:
    u = User.find(...)
    u.role #=> John or Pimp

  7. #7
    SitePoint Member
    Join Date
    Jun 2008
    Posts
    10
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the input everyone.

    I have been struggling with this mostly as a logical leap my head has refused to make. In terms of the polymorphic => true setup, I don't get how I could have Pimps and Johns having a User (which means the User belongs to them - even as a role). Then how do I establish the user first... I would have User created before the Pimp that owns it?

    I'm going to try setting up a form that enters both Models' data and hope that it goes, but I have no confidence.

  8. #8
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can create the user and the pimp seperately and link them with `joe.role = the_pimp_object`.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •