Rails Has_one and has_many relationship - ruby-on-rails

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.

Related

Modeling schools database

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
.

How to do `has_one: model, through: join_model` in JSONAPI::Resource

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.

Should this has_many :through relationship be polymorphic or not?

I have a many-to-many relationship setup for Teachers and Classrooms via has_many :through:
class Teacher < ActiveRecord::Base
has_many :classrooms, :through => :classroom_memberships
end
class Classroom < ActiveRecord::Base
has_many :students
has_many :teachers, :through => :classroom_memberships
end
class ClassroomMemberships < ActiveRecord::Base
belongs_to :teacher
belongs_to :classroom
end
Currently, Students can only belong to one Classroom:
class Student < ActiveRecord::Base
belongs_to :classroom
end
Now I have the need to track historical classroom memberships for students, creating a second many-to-many relationship for classrooms. So, while a student can only belong to one classroom at a time, I need to know that last year, student A belonged to classroom B.
I'm thinking I have two viable options:
1.) Make the classroom_memberships association polymorphic so I'd have a classroomable_id and classroomable_type that would point to either a teacher OR a student.
2.) Simplify things and add another foreign key to ClassroomMemberships called student_id, in which case, for a given row, either student_id OR teacher_id would have a value.
Which is the better option?
I would probably go the route of:
class Course < ActiveRecord::Base
# like "MATH 100"
has_many :sections
has_many :teachers, :through => :sections
end
class Term < ActiveRecord::Base
# like "Fall 2015"
has_many :sections
end
class Teacher < ActiveRecord::Base
has_many :sections
has_many :courses, :through => :sections
end
class Section < ActiveRecord::Base
# a course, in a term, taught by a teacher, with registered students
belongs_to :term
belongs_to :course
belongs_to :teacher
has_many :registrations
has_many :students, :through => :registrations
end
class Registration < ActiveRecord::Base
# a student in a specific section
belongs_to :section
belongs_to :student
end
class Student < ActiveRecord::Base
# a student's registrations are their course history
has_many :registrations
has_many :sections, through :registrations
end
As a start, since this is a fairly basic modeling of an educational system.
It sounds like maybe you want a ClassroomMembershipHistory model.
Something like
class ClassroomMembershipHistory < ActiveRecord::Base
belongs_to :student
belongs_to :classroom
end
with a year attribute, stored however is easiest to query for your use case.

Ruby on Rails - Association

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

Rails/Active Record polymorphic association needed?

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.

Resources