我是Rails的新手,我正在尝试创建一个应用程序,其中用户可以拥有许多教室,而教室可以有许多用户。但是,我不确定如何设置模型。
假设我有一位叫乔的老师。乔有很多教室。乔的每个教室可以有很多学生,因此从这些教室中,乔也有很多学生。但是我也希望Joe能够作为学生成为教室的一部分,并且我希望学生能够从同一个帐户创建自己的教室(作为老师)。
教室也应该可以有多个老师。
我还希望能够执行诸如user.classrooms.first.users之类的操作,其中用户是Joe,而用户是他在第一个教室中的学生。
我应该创建什么模型,以及如何建立关联?
我当时在想has_and_belongs_to_many
,但是显然不再受青睐了,has_many :through
会更好。对我来说,它看起来像:
class User
has_many :classroom_users
has_many :classrooms, :through => :classroom_users
end
class Classroom
has_many :classroom_users
has_many :users, :through => :classroom_users
end
class Classroom_User
belongs_to :classroom
belongs_to :user
end
这样对吗?我从here那里拿走的。
另外,我该如何通过迁移在数据库中镜像这些模型?
最佳答案
将用户与教室(而不是教师)相关联的情况下,您目前所拥有的将适用,因为目前将两种模式相关联的表只能表示一种关系。
注意:Rails希望模型名称为单数形式且不带下划线,即示例中的ClassroomUser
而不是Classroom_Users
。
要将教师与教室联系起来,一种方法是创建一个额外的加入模型:
user.rb:
class User < ActiveRecord::Base
has_many :classroom_teachers
has_many :classroom_students
has_many :teaching_classrooms, through: :classroom_teachers
has_many :attending_classrooms, through: :classroom_students
end
课堂.rb:
class Classroom < ActiveRecord::Base
has_many :classroom_teachers
has_many :classroom_students
has_many :teachers, through: :classroom_teachers
has_many :students, through: :classroom_students
end
课堂学生.rb:
class ClassroomStudent < ActiveRecord::Base
belongs_to :student, class_name: 'User', foreign_key: 'user_id'
belongs_to :attending_classroom, class_name: 'Classroom', foreign_key: 'classroom_id'
end
school_teacher.rb:
class ClassroomTeacher < ActiveRecord::Base
belongs_to :teacher, class_name: 'User', foreign_key: 'user_id'
belongs_to :teaching_classroom, class_name: 'Classroom', foreign_key: 'classroom_id'
end
Rails通常会根据字段名称(例如,
users
字段将链接到User
模型的集合。使用上述模式,Rails无法从关联字段的名称推断模型的类型,因为它不知道teacher
是user
的别名。为了克服这个问题,class_name
属性定义了连接字段的模型类型。出于同样的原因,Rails需要一些指导,以了解哪些数据库密钥与哪个字段相关,即
foreign_key
属性的含义。最后是迁移:
class CreateClassroomUsers < ActiveRecord::Migration
def change
create_table :users do |t|
end
create_table :classrooms do |t|
end
create_table :classroom_students do |t|
t.belongs_to :user, index: true
t.belongs_to :classroom, index: true
end
create_table :classroom_teachers do |t|
t.belongs_to :user, index: true
t.belongs_to :classroom, index: true
end
end
end
编辑:
另外,也可以不使用两个联接模型,而可以在原来的
ClassroomUser
模型中添加一个额外字段,以描述用户的角色(例如,可以为student
或teacher
的enum) 。这将允许将来添加更多角色,并且比我以前的建议更容易查询。例如,要检查用户是学生还是老师,您只需要一个查询:example_user.classroom_users
然后可以检查返回的
ClassroomUser
记录上的角色字段。有关该方法的示例,请参见this question。