user972276
user972276

Reputation: 3053

Using join tables in ruby on rails

Lets say I have two databases: one for students and one for classes. I would like to be able to 'add' classes to a specific student and also be able to add students to a specific class. I assume I need to use a join table here but I am a little lost on how to use them. I would ultimately like to be able to do something like:

  @class.students.find(@student_id)

and this would tell me if the student is in the class or not. I know the relationship between classes and students is 'has_many' and vice versa. Does doing 't.references :students' in the migrate files accomplish that? I tried adding that line to my migrate file and then tried finding something using the statement above and it gave me an error. I am new to RoR so I am not even sure what the best way to go about achieving this is. Any help is appreciated!

Upvotes: 29

Views: 67398

Answers (3)

StephanieS
StephanieS

Reputation: 443

This is an old question, but just in case anyone stumbles upon this like I did, you can now have the relationships has_and_belongs_to_many. So yes, you would create a join table:

create_join_table :students, :courses do |t|
  t.integer :student_id
  t.integer :course_id
end

And then in the models, you would say that a student has_and_belongs_to_many :courses And a course has_and_belongs_to_many :students. There is no need to make a third class called CourseStudent. This link has all this information

Upvotes: 23

mliebelt
mliebelt

Reputation: 15525

Everything true what @Jordan said, here the concrete steps to take:

  1. Create a migration: rails g model CourseStudent creates a join model for the n:m relation, and the migration to the corresponding table.
  2. Edit the migration file CreateCourseStudent so it contains the following:

    class CreateCourseStudent < ActiveRecord::Migration
      def change
        create_table :course_students do |t|
    
          # Your code comes here
          t.integer :student_id
          t.integer :course_id
    
          # Here comes the generated code 
          t.timestamps
        end
      end
    end
    
  3. Run the migration: rake db:migrate. As a result, the join table should now exist in your database.

  4. Add to the models the following code

    class Course < ActiveRecord::Base
      has_many :course_students
      has_many :students, :through => :course_students
    end
    
    class Student < ActiveRecord::Base
      has_many :course_students
      has_many :courses, :through => :course_students
    end
    
    class CourseStudent < ActiveRecord::Base
      belongs_to :student
      belongs_to :course
    end
    

You are now able to use the methods generated by the methods belongs_to and has_many:

  • @course.students
  • @student.courses

Try to find all the relevant facts and snippets in the Rails Guides, there you should find all information you need to get on track. Good luck!

Upvotes: 75

Jordan Running
Jordan Running

Reputation: 106027

Yes, this is a many-to-many relationship (class has many students, student has many classes). For this you'll use a has_many :through relation. Take a look at the docs for ActiveRecord::Associations (Ctrl-F for "Association Join Models").

In a migration, t.references :students is how you would specify a belongs_to relation, as it just adds a student_id column (which can only accommodate one id, i.e. one student). A join model, however, will have two columns: student_id and class_id. (Incidentally, calling a model 'Class' in Ruby is asking for trouble. Might I suggest 'Course'?)

Upvotes: 18

Related Questions