简体   繁体   中英

RAILS User hierarchies; classes, associations. Polymorphic?

I'm amazed at how hard it is to still find a definitive answer to this: it seems so common that I must be looking at it all wrong.

We have Users, who's authorization roles run something like ROLES = %w[admin moderator teacher student banned]

It's commonly recommended to use a ROLES field and Single Table Inheritance to (as here )

class User < ActiveRecord::Base
end

class Student < User
end

class Teacher < User
end

But this puts all the data in one table. What if we have a good bit of data unique to each user type?

student
  year:integer
  request_id:integer
  portfolio_id:integer
  status:string
  ...

teachers
  user_id:integer
  district:string
  school:string
  subject1:string
  subject2:string
  specialty:string
  bio:text
  ...

STI gives things like student.specialty and teacher.portfolio_id, which we don't want and would have to block.

The Ruby Way suggests Abstract Base Model Class to handle separate tables:

class User < ActiveRecord::Base
  self.abstract = true
end

class Student < User
end

class Teacher < User
end

Which will allow unique tables for both Student and Teacher. However, he warns, User.find(:all) won't work. Plus, there's the common attributes we wanted, which was the whole point of a User model:

User
  username:string
  email:string
  password:string
  role:string

Since there's no User table, there's no common attributes?

Various other answers hint at using :polymorphic => true , :class_name => 'User' , or as: but all explained more like adding a Comments to both a post and an image. Which doesn't seem a good parallel.

I seem to recall at least one language (and maybe a couple OODB's) which simply used the IS-A relationship to inherit attributes.

What's the RAILS way?

I think STI is the wrong to do here. You have too many things going on that would be shoved into one table.

I would rather do a generic User model, holding the common stuff like e-mail, name and for each user type have a separate model (and table). So, teachers and students would reference users, but have their own fields.

Roles should also be in their own table separate from users.

Reference the user record like this:

class Teacher < AR::Base
  belongs_to :user
end
class Student < AR::Base
  belongs_to :user
end
class User < AR::Base
  has_one :teacher
  has_one :student
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM