我是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无法从关联字段的名称推断模型的类型,因为它不知道teacheruser的别名。为了克服这个问题,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模型中添加一个额外字段,以描述用户的角色(例如,可以为studentteacherenum) 。这将允许将来添加更多角色,并且比我以前的建议更容易查询。例如,要检查用户是学生还是老师,您只需要一个查询:

example_user.classroom_users


然后可以检查返回的ClassroomUser记录上的角色字段。有关该方法的示例,请参见this question

09-25 17:10