Search code examples
ruby-on-railsrubyruby-on-rails-5

How to create a one to many relation between models in Ruby on Rails?


I've students and courses in my ruby models and controllers, so i want to connect this two things and show an user and the courses he have registered and click those courses to see what is inside that course. i'm new to ruby so i don't know much about has_many and i cant find something that can make what i want to work

i've use scaffold to create the models and controllers, user only have a name, email and courses only have course_name

student:

 create_table :student do |t|
      t.string :name
      t.string :email

course:

create_table :course do |t|
  t.string :name

  t.timestamps

in the index of students i only list all of the students i have. help please


Solution

  • Looks like you want to use a many-to-many association between students and courses. There are a number of ways to achieve this. I would go with the has_many :though option described here, in which you add an additional model called StudentCourse.

    So in your scenario, you would:

    1. generate this StudenCourse model with rails generate model StudentCourse student:references model:references

    2. add the following to your Student model

        class Student
          ...
          has_many :student_courses
          has_many :courses, through: student_courses
          ...
        end
    
    1. add the following to your Course model
        class Course
          ...
          has_many :student_courses
          has_many :students, through: student_courses
          ...
        end
    
    1. run migrations with rake db:migrate
    2. now you can start adding students to courses and vice versa. For example:
        Student.last.courses << Course.last
        Course.first.students << Student.first
    

    and in your controllers, you can simply call student.courses to see courses that are associated with a given student, or course.students to view students taking a specific course.

    notice how both Course and Student models will are now associated with each other using has_many: ..., through: :student_courses.

    Another benefit of using this type of many-to-many association is flexibility. For instance, you might want to start recording whether students have dropped specific courses. You can do so by simply adding a dropped_at column to this new student_courses table.

    EDIT

    adding a few more detailed examples of how to use this new association:

    as mentioned, you can append courses to students and vice versa via rails console. For instance, a student with id of 1 wants to enroll into a course with id of 2:

    Student.find(1).courses << Course.find(2)
    

    similarly, you can just add students to courses like so:

    Course.find(2).students << Student.find(1)
    

    under the hood, both of these associations would be creating a new instance of the StudentCourse class we added. So a third option of creating this association would be:

    StudentCourse.create(student: Student.find(1), course: Course.find(2))