问题
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?
回答1:
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
来源:https://stackoverflow.com/questions/9006918/rails-user-hierarchies-classes-associations-polymorphic