I am making a school application where a list of courses is needed for both the lecturers and the students, a list of lecturers for the students and a list of students for the lecturers.
So I have three models: staff, student and course.
I am new to RoR and associations don't make the most sense to me right now, but I want each staff and student to have multiple courses. So I thought has_many and belongs_to. Then I want each student to have a list of his/her lecturers, so has_many :staff, through: :course and the same for staff has_many :student, through: :course. I also want to use a paticular column for the relation, say course_code not an id.
staff.rb
has_many :courses
has_many :students, through: :courses
student.rb
has_many :courses
has_many :staff, through: :courses
course.rb
belongs_to :staff
belongs_to :students
Would this be the best way to do it if I want to be able to do #student.course.all and #student.lecturer.all?
If you want both students and lecturers to have courses, you'll need to use a polymorphic association.
https://guides.rubyonrails.org/association_basics.html#polymorphic-associations
Here's a guide that tells you how to implement!
EDIT: You don't need to use a polymorphic association, but it'll help DRY out your code. In addition, use concerns!
EDIT: Also, I think you need a join table. (A course can have many students, and a student can have many courses).
So a student can follow many courses, staff can teach many courses, a courses is followed by 1 or more students, and it is teached by 1 or more staff. Reading this: you need a join table.
Still as usual, there are many different approaches to do this. Let me start with the simplest first: create two join-tables: followed_courses and lectured_courses.
Class FollowedCourse
belongs_to :student
belongs_to :course
Class LecturedCourse
belongs_to :lecturer
belongs_to :course
Class Course
has_many :followed_courses
has_many :students, through: :followed_courses
has_many :lectured_courses
has_many :lecturers, through: :lectured_courses
Class Lecturer
has_many :lectured_courses
has_many :courses, through: :lectured_courses
Class Student
has_many :followed_courses
has_many :courses, through: :followed_courses
("Staff" is a confusing word in ruby on rails, since it has no plural: how do you indicate a group op staff versus a single staff member, that's why I propose lecturer here, but of course you could use teacher or anything similar).
What I could imagine is that a person, sometimes has the role of student, and sometimes the role of a teacher, so you could have a different join-table, called ParticipatingCourses where it belongs_to a person and a course, and has a role to indicate in which way they participate: student or lecturer. This makes things a little harder, so I think for now it would be simpler to stay with my first proposal.
Related
I have searched and searched and found only partial solutions to my current question.
The thing is, I'd like to know if it is possible to use has_many :through along with a polymorphic association in Ruby on Rails.
I have a system where students can create travel plans (that can belong to many students) and refund claims (that can belong to only one student) for their projects. In this system, both admin users and students are able to comment on the plans and claims.
My associations are:
class Student < ActiveRecord::Base
has_and_belongs_to_many :travel_plans
has_many :refund_claims
has_many :comments, through: :travel_plans
has_many :comments, through: :refund_claims
end
class AdminUser < ActiveRecord::Base
has_many :comments
end
class TravelPlan < ActiveRecord::Base
has_and_belongs_to_many :students
has_many :comments, as: :commentable
end
class RefundClaim < ActiveRecord::Base
belongs_to :student
has_many :comments, as: :commentable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
My questions are:
Is it correct to associate comments twice in the Student model?
I don't want the AdminUsers to have travel plans and refund claims, how can I identify their comments as being made on a travel plan or on a refund claim?
Would there be a better approach?
Thanks a lot in advance for everyone!
Cheers,
You probably want to add an polymorphic author attribute to the Comment model. Than you just need has_many :comments, as: :author to the Student and AdminUser model.
If this is a new application and you are starting on the green field you might want to rethink your models a bit and add a Role and a User model. Student would than be a role of user as would AdminUser be.
Is it correct to associate comments twice in the Student model?
No, not really. If you have duplicate association name, you can only use one of them. If you want to use both, you have to name them differently.
Rails newbie here.
While porting models from Django's to Rails I'v got confused with finding best relationships...
Models i want to implement:
Role (has many Users and Teams)
User (has many Roles and Software)
Software (has many Users and one Team)
Team (has many Software and Documents)
Patch (has many Teams and Software)
Document (has many Teams and Software)
Is it possible to build associations with has_many: through or better use has_and_belongs_to ?
I think :through associations will be complicated, 'cause there is more than two cross-relations with given models.
I can see two ways of doing relationships: one big join model or small join models for all current many-to-many relations between models.
class Role
has_many :relations
has_many :users, through: :relations
has_many :teams, through: :relations
end
class User
has_many :relations
has_many :roles, through: :relations
has_many :software, through: :relations
end
class Team
has_many :relations
has_many :software, through: :relations
end
class Software
has_many :relations
has_many :users, through: :relations
has_one :team
end
class Relation
belongs_to :user
belongs_to :role
belongs_to :teams
belongs_to :software
end
has_many :through gives you the extra flexibility of having a fully functional join model class. This is required in cases where you want to model some aspects of a relationship beyond the simple fact that the two things are associated with one another.
There's no downside to has_many :through as far as i know, other than your codebase might be a line or two bigger, and plenty of advantages. I would always use has_many: through
re the associations being complicated: draw them all out with a paper and pencil (or a UML-drawing app if you prefer), before doing any coding. If you previously had a working django app it should be simple enough to map the schema across: they are both object-relational systems.
I have 3 Models: Vote, Student and Teacher. A Student can give a vote for either another student or a teacher. Previously a student could only give a vote for one student or one teacher. But now i want to have the option to vote for multiple students and teachers. The vote model additionaly stores a category_id and a rating, so that you can give different rated votes in the same category. For the polymorphic many-to-many relation between vote and Teacher/Student i use a fourth model called SingelVotedRelation, which has the attributes vote_id, voted_id and voted_type.
Now i want to have the ability to call vote.voted and get a collection of the voted persons (student or teacher) without having to mess around manually with the SingleVotedRelation Table:
has_many :voted, through: :single_voted_relations
But i get error messages when i tried this. My working Vote Model looks like this:
belongs_to :voter, class_name: "Student"
has_many :single_voted_relations
has_many :voted_students, through: :single_voted_relations, source_type: "Student", source: :voted
has_many :voted_teachers, through: :single_voted_relations, source_type: "Teacher", source: :voted
SingleVotedRelation looks like this:
belongs_to :vote
belongs_to :voted, polymorphic: true
Student:
has_many :given_votes, class_name: "Vote", foreign_key: "voter_id"
has_many :single_voted_relations, class_name: "SingleVotedRelation", as: :voted # polymorphic
has_many :achieved_votes, source: :vote, through: :single_voted_relations
Teacher:
has_many :single_voted_relations, class_name: "SingleVotedRelation", as: :voted # polymorphic
has_many :achieved_votes, source: :vote, through: :single_voted_relations
I basically just want to join the voted_students and voted_teachers relations from the Vote-Model into one voted relation, which contains the students and also the teachers.
This may be too complicated and there could be a smarter way to achieve my goal.
Is it even possible to have different source types?
Help is appreciated
Thanks!
I am beginning my first rails application and I would just like to make sure that my associations will work like I am hoping. Here is an overview of the models in my application:
class School < ActiveRecord::Base
has_many :courses
has_many :teachers, :through => :courses
has_many :students, :through => :courses
end
class Course < ActiveRecord::Base
belongs_to :school
belongs_to :teacher
has_and_belongs_to_many :students
end
class Teacher < ActiveRecord::Base
has_many :courses
has_many :students, :through => :courses
end
class Student < ActiveRecord::Base
has_and_belongs_to_many :courses
has_many :teachers, :through => :courses
end
The one thing I have noticed so far is that if I try to get the teachers or students in a school it will return the same record multiple times. I am aware I can just call uniq but I would prefer not having to doing that. So I am wondering if there is a better way I can do this.
Were it me, I would not subordinate teachers or students to courses, but to the school directly. Does a teacher not exist without a course? Likewise a student?
And I'd use defined models for linking teachers and students to courses, not the generic habtm -- defined models let you easily store additional attributes - students might have grades for courses for instance.
Perhaps:
School, has many faculty, has many students, has many courses.
Faculty, has many teachings, has many courses through teachings.
Student, has many registrations, has many courses through registrations.
Course, has many registrations, has many students through registrations, has many teachings, has many faculty through teachings.
Teaching, belongs to faculty, belongs to course.
Registration, belongs to student, belongs to course.
Regarding your interest in a unique constraint, you can actually specify the has_many :through to only return unique records.
has_many :teachers, through: :courses, -> { distinct }
Check out the Rails Guide on the topic.
Regarding an additional :school_id, If a Student or Teacher's association to a School is defined purely by their enrollment in or teaching of a Course, I see no immediate issue with not specifying a :school_id column on your Teacher and Parent
I'm in the process of trying to develop my first rails application and before I jump off into actually implementing my ideas, I was hoping I could get some help with my association planning.
My application is going to be an educational tool and I have some basic functionality that I need to implement. I want to have students that can register for and create courses. Within these courses, there will be one user who is the teacher and the rest are students. Within the course will be assignments that the teacher creates and that users are required to make a submission for. These are the basics. Eventually I want to add more functionality but as of now I just need the foundations set.
Here are my ideas so far on what the associations should look like:
class User < ActiveRecord::Base
has_many :enrollments
has_many :courses, :through => :enrollments
end
class Course < ActiveRecord::Base
has_many :enrollments
has_many :users, :through => :enrollments
end
class Enrollment < ActiveRecord::Base
belongs_to :user # foreign key - user_id
belongs_to :course # foreign key - course_id
end
However, I'm running into my wall of inexperience at the moment with how to appropriately handle the rest of the associations at this point. I could probably hack out something, but I'd prefer to do it as best as I can the first time.
How do I handle the associations related to assignments and submissions? Presumably a student's submission should belong_to them, but it is also specifically related to an assignment within the class. Assignments originate within a course, but are also closely tied to the user.
Finally, what's the best way to handle the relationships between a user and the class they create? A user creates a course. Does that course belong_to them? Should I just add a column to the course's table for storing the creator's id? Etc.
Thanks for the help.
Suggestion:
You might want to separate out your Teacher and Student models, since you're very likely to have different actions associated with each (and while they share some attributes, they really are different entities in your model, for example, you likely want just one teacher teaching in a course.)
You could derive both the Teacher model and the Student model from a User model that has the shared attributes and authentication.
Now to your questions:
If you'd like to keep the student that created the course associated, creator_id is the way I'd go. (If a teacher can create a course too, deriving Student and Teacher from a shared User model would help)
Assignments and Submissions:
You've pretty much defined it in words. Here is the code.
[If different students within a course could get different assignments, only then do you want to build a direct association between Student and Assignment, otherwise, use a through association]
class User < ActiveRecord::Base
has_many :enrollments
has_many :courses, :through => :enrollments
has_many :assignments, :through => :courses
has_many :submissions
end
class Course < ActiveRecord::Base
has_many :enrollments
has_many :users, :through => :enrollments
has_many :assignments
end
class Enrollment < ActiveRecord::Base
belongs_to :user # foreign key - user_id
belongs_to :course # foreign key - course_id
end
class Assignment < ActiveRecord::Base
belongs_to :course
has_many :submissions
end
class Submission < ActiveRecord::Base
belongs_to :assignment
belongs_to :user
end