Here what i need:
School has many teachers
Teachers can belong to one or more schools
Subject can belong to one or more teachers
Teachers can has many subjects
How can i make a relationship that store:
Teacher A works in School 1 and School 2, but he teach math and physics in he School 1 and only math in the School 2?
Here what im already done:
class School < ApplicationRecord
has_many :school_teachers
has_many :teachers, through: :school_teachers
end
class Teacher < ApplicationRecord
has_many :school_teachers
has_many :schools, through: :school_teachers
end
class SchoolTeacher < ApplicationRecord
belongs_to :school
belongs_to :teacher
end
class Subject < ApplicationRecord
end
Since a subject is associated with one or more school & teacher pairings, then I would suggest this may really be a 3-way "has and belongs to many" relationship.
class School < ApplicationRecord
has_many :school_teacher_subjects
has_many :teachers, through: :school_teacher_subjects
has_many :subjects, through: :school_teacher_subjects
end
class Teacher < ApplicationRecord
has_many :school_teacher_subjects
has_many :schools, through: :school_teacher_subjects
has_many :subjects, through: :school_teacher_subjects
end
class Subject < ApplicationRecord
has_many :school_teacher_subjects
has_many :schools, through: :school_teacher_subjects
has_many :teachers, through: :school_teacher_subjects
end
class SchoolTeacherSubject < ApplicationRecord
belongs_to :school
belongs_to :teacher
belongs_to :subject
end
Here's an example of a 3-way HABTM relationship for customers, phones, and addresses: Custom db entry for 3 way habtm in ROR
.
Related
I want to design a club system. A club has many users, a user has one club, and a membership to store some info.
Can I use has_one :through and has_many :through to build one-to-many associations?
class Club < ApplicationRecord
has_many :users, through: :memberships
has_many :memberships
end
class Membership < ApplicationRecord
belongs_to :club
belongs_to :user
end
class User < ApplicationRecord
has_one :club, through: :membership
has_one :membership
end
Because in the Rails Guides, it mentions has_one :through to build one-to-one association, and has_many :through to build many-to-many association.
Can I use this way? Thanks.
You can. You have to adjust your models a bit to define your through part before defining another association that goes through it, i.e.
class Club < ApplicationRecord
has_many :memberships
has_many :users, through: :memberships
end
class User < ApplicationRecord
has_one :membership
has_one :club, through: :membership
end
I have Teacher model:
class Teacher < User
has_many :categories, dependent: :destroy
has_many :grades, through: :categories
end
Grade model:
class Grade < ApplicationRecord
has_many :categories, dependent: :destroy
has_many :teachers, through: :categories
end
Category model:
class Category < ApplicationRecord
belongs_to :teacher
belongs_to :grade
end
Student model:
class Student < User
end
Now i want to set up relationship between Grade model and Student model
(student has_one grade and a grade has_many students) with through model Category.
How can i do this?
class Student < User
has_one: :grade
end
and
class Grade < ApplicationRecord
has_many :categories, dependent: :destroy
has_many :teachers, through: :categories
has_many :students, through: :categories
end
and
class Category < ApplicationRecord
belongs_to :teacher
belongs_to :grade
belongs_to :student
end
Does the above not work..? You should put what you have tried in your post if you have run into issues.
Join tables are for many-to-many relationships. Since a student only has one grade, it is a many-to-one relationship, not a many-to-many relationship.
You do not need (and shouldn't use) a join table for this.
Instead add a grade_id column to the students (users) table and setup the associations like this:
class Student < User
belongs_to :grade
end
class Grade < ApplicationRecord
has_many :students
end
Don't use any through associations to connect students with grades.
What's the preferred way to do has_one :model, through: join_model in a model resource? Usually JSONAPI::Resource expects model_id column on the table/model who owns the association. That does not exist if a join table/model is used.
You can actually just mention the has_many relationship, with no need to mention the through association.
So if you had this model structure:
class Teacher < ActiveRecord::Base
has_many :classrooms
has_many :students, through: :classrooms
end
class Student < ActiveRecord::Base
has_many :classrooms
has_many :teachers, through: :classrooms
end
class Classroom < ActiveRecord::Base
belongs_to :teacher
belongs_to :student
end
In your Teacher resource, all you'd need is has_many :students.
And likewise, in your Student resource, you'd need has_many :teachers.
I have to create relationship between student, courses and enrolment.
One student can enrol in only one course.
A course can be enrolled by many students.
How to acheive this ?
I was able to create has_many_through relationship like this
class
Student < User
has_many :enrollments
has_many :course , through: :enrollments
end
class Course < ActiveRecord::Base
has_many :enrollments
has_many :students, through: :enrollments, class_name: "User"
end
class Enrollment < ActiveRecord::Base
belongs_to :student, class_name: "User"
belongs_to :course
end
But this works only for has_many on both the sides of students and courses.
But I want only one student to enrol in one course like this
class Student < User
has_one :enrollment
has_one :course , through: :enrollment
end
But this does not work. When I do this
Student.first.enrollment.create(course: Course.last)
I get an error like this
NoMethodError: undefined method `enrollment' for #<Student:0x007f7ff8baf4a8>
Thanks to Marek Lipka for suggesting this solution.
Add validation in Enrollment
class Enrollment < ActiveRecord::Base
belongs_to :student, class_name: "User"
belongs_to :course
validates :student , uniqueness: true
end
And use has_many enrollments
class Student < User
has_many :enrollments
has_many :course , through: :enrollments
end
I have 3 models, a School which has many Teachers and Students. The problem is that Students can belong to either a School or a Teacher, so theoretically they always belong to a School through association. How would I deal with this type of data structure in Rails/Active Record?
class School < AR::Base
has_many :teachers
has_many :students
end
class Teacher < AR::Base
belongs_to :school
has_many :students
end
class Student < AR::Base
belongs_to ???
end
This solution should work, but you I have a doubt about your introduction ; you say that "a teacher have many student". This sentences implies "a student has ONE teacher".
Maybe you should set an has_and_belongs_to_many association.
class School < AR::Base
has_many :teachers
has_many :students, :through => :teachers
end
class Teacher < AR::Base
belongs_to :school
has_many :students
end
class Student < AR::Base
belongs_to :teacher
belongs_to :school, :through => :teacher
end
Clearly you need polymarphic association, can be done as
class School < AR::Base
has_many :teachers
has_many :students, :as => :studentable
end
class Teacher < AR::Base
belongs_to :school
has_many :students
end
class Student < AR::Base
belongs_to :studentable
end
don't forget to add studentable_id and studentable_type to student model.