То, что у вас есть на данный момент, будет работать в случае связывания пользователей с классами, но не учителей, поскольку на данный момент таблица для связывания двух моделей может обозначать только один тип отношений.
NB: 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 не может вывести типы моделей из имен связанных полей, поскольку он не знает, что 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
, описывающей роль пользователя (например, enum, который может иметь значение student
или teacher
). Это позволит добавить больше ролей в будущем и, возможно, будет проще запросить, чем мое предыдущее предложение. Например, чтобы проверить, является ли пользователь учеником или учителем, вам понадобится только один запрос:
example_user.classroom_users
и затем может проверить поля ролей в возвращенных ClassroomUser
записях. См. Пример в этом вопросе. этого подхода.
person
tmw
schedule
28.11.2015