Niels B.
Niels B.

Reputation: 6310

Role-dependent associations

I am working on my first real Rails app for timetracking in a company and I have run into database/model design concern. My app has a User model and a Role model which are linked together through a has_and_belongs_to_many association.

One of the roles is the manager. A manager can have many assistants and assistants can have many managers (although typically only one). This relationship is represented through a manager_assistant_relationship expressed in the User model as:

has_many :assistants, :through => :manager_assistant_relationships
has_many :managers, :through => :manager_assistant_relationships

Assistants can have many shifts (a different model representing a work shift) and managers can have many clients (another model that will be billed for the assistants' work). And more associations are coming.

As far as I can tell the only solution is to put all these relationships in the User model, but something feels wrong about this and the User model could get bloated as roles increases and associations mount and it also seems unintuitive, because a User only has many assistants if he is a manager. I would like some advice about potential pitfalls to this approach and what alternatives I should consider.

Would it be a good idea to subclass the User model into roles?

Upvotes: 3

Views: 949

Answers (1)

joelparkerhenderson
joelparkerhenderson

Reputation: 35453

Good news, you're doing it correctly with roles.

To answer your question, no it is not a good idea to subclass the User model for what you describe. If you did, it tends to lead to tricky self-joins for associations, or to STI (single table inheritance), or to inheritance or classes instead of composition of modules. Much better to use roles.

It may help you to think of the user as a person, not a role. So the User class contains just personal information, such as name, birthdate, height, and maybe an email address, sign in password, etc. Make the personal information separate from the time tracking role.

To use your roles, you can do model relationships like this psuedocode:

 class Manager
   has_many :clients
 end

 manager = Manager.find(id)
 client = manager.clients.first

Or like this pseudocode:

 class Assistant
   has_many :workshifts
 end

 assistant = Assistant.find(id)
 workshift = assistant.workshifts

Other good reasons to prefer using roles is for Role-Based Access Control (RBAC) and for Data Context Interation (DCI) if you want to read up on these.

Upvotes: 1

Related Questions