【问题标题】:Users/Classroom Associations用户/课堂协会
【发布时间】:2016-03-02 03:36:19
【问题描述】:

我是一个相当新的 Rails 新手,我正在尝试创建一个用户可以拥有许多教室的应用程序,并且教室可以拥有许多用户。但是,我不确定如何设置模型。

假设我有一位名叫乔的老师。乔有很多教室。 Joe 的每个教室都可以有很多学生,所以在这些教室里,Joe 也有很多学生。但我也希望 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 拿来的。 另外,我应该如何通过迁移在数据库中镜像这些模型?

【问题讨论】:

    标签: ruby-on-rails associations model-associations


    【解决方案1】:

    您目前所拥有的内容适用于将用户与教室相关联的情况,但也不适用于教师,因为目前关联这两个模型的表格只能表示一种关系。

    注意: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
    

    classroom.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
    

    classroom_student.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
    

    classroom_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 模型中添加一个额外字段来描述用户的角色,而不是使用两个连接模型(例如,enum 可以是student 或@ 987654338@)。这将允许将来添加更多角色,并且可能比我之前的建议更容易查询。例如,要检查用户是学生还是教师,您只需要一个查询:

    example_user.classroom_users
    

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

    【讨论】:

    • 非常感谢!真的有帮助!
    • 没问题。我在帖子末尾做了一个小修改,因为我不确定我的原始答案是否是您尝试建模的最佳解决方案。
    • 如果我想将一个已经存在的用户添加到一个已经存在的教室,我该怎么做呢?我试过Classroom_Student.create!(user_id: example_user, classroom_id: example_classroom),但它不起作用。这就是我得到的:Unable to autoload constant Classroom_Student, expected app/models/classroom_student.rb to define it.
    • 你应该去掉下划线并使用ClassroomStudent(见我回答的第二段)。然后您可以使用以下方式创建关系:ClassroomStudent.create(user: example_user, classroom: example_classroom)example_user.classrooms &lt;&lt; example_classroomexample_classroom.users &lt;&lt; example_user。我假设您原始示例中的字段名称,因此如果您使用了我的答案中的字段名称,请酌情更改它们。
    猜你喜欢
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多