Modeling many types of users

Looking for some input on modeling a user system.

The user system is for schools. We have many potential types of users, and we need to be extremely flexible in the design as the system will be used at different school districts in different states.

Single table inheritance doesn't really work as we would end up with many attributes that don't apply to one type of user or another. Creating a model for each user type is also problematic for authorizing users and handling logins. We also have an access control model that uses permissions and groups, but I won't go into that here.

So what I was thinking is that we have a simple user model, something like what is used in acts_as_authenticated.

Then we have a Profile model (couldn't think of a better name) that contains all the attributes for particular types of users. Attributes could be a name, email address, school district, courses taught, etc.. So we would have a StudentProfile, TeacherProfile, etc.. We would probably have an abstract UserProfile also to stick methods and attributes that are common to all profile types.

Anyone think of a simpler way of doing this?

Chris

I would check out the role-based authentication from Rails Recipe or you can see a revised (better) version of that recipe here:

http://daveastels.com/2006/08/29/role-based-authentication-from-rails-recipes-part-1/ http://daveastels.com/2006/08/29/role-based-authentication-from-rails-recipes-part-2/

You basically model Users, their Roles (student, teacher, admin, etc.), and then the Rights associated to a particular Role. The solution is flexible and allows you to control what Roles are allowed to do at the controllers / actions level.

Hope that helps!

Without thinking it through completely and really thinking out loud :wink: The thought of “mixing” in an active record model into another model might conceptually be schwoit.

Basically delegate the method missing to each mixed in model until something responds. Use after save etc to save the associations etc. What I have in my head is similar to mixing in a module, but your mixing in a persistent model. Perhaps some copious use of with_scope might help.

As I said, I haven’t thought this completely through, but it seems like it would be slow but flexible if it’s possible.

Cheers Daniel

Don't think of user types as a matter of inheritance, think of it as
a property. So, you have generic users and they have relationships
to other tables that give them the desired properties. In fact, you
could make it a polymorphic association. For example:

User { username, password, first_name, last_name, dob }

UserTypeA { wierd_attr_1, wierd_attr_2, wierd_attr_3 } UserTypeB { wierd_attr_A, wierd_attr_B, wierd_attr_C} UserTypeC { wierd_attr_x, wierd_attr_y, wierd_attr_z }

So user carries the core, common information. The different UserType {A, B, C} tables carry information specific to that type of user. As
a more concrete example, for one client we modeled invoices and
payments. Each payment can be a credit card payment, check payment,
or electronic transfer. (This affects how refunds are handled when a
payment is canceled.)

An invoice has many payments and each payment has a payment_info
polymorphic reference. That payment_info can be a credit_card_info,
check_info, or transfer_info. If we were to add a new type of
payment (say e-check) we could add an echeck_info to the model fairly
easily. See AWDR2 - pages 346-349.

has_many_polymorphs to the rescue :slight_smile: http://blog.evanweaver.com/pages/code#polymorphs