I would like to understand the process which can be followed to create models and migrations which in turn create a joining table within the database to resolve a many-to-many relationship. For instance. If i have a course table, a students table and i want to create a joining table called studies with the id from course and students along with extra data such as the grade and date started. Exactly What is the process for doing this? If i am to use the generate model command for each of the above 3 table names, this will create a separate migration for all of them. Even if i go into the models and add the relevant associations this will not affect how the database is created? Please could you give me some guidance on what steps i must take in order to create the required foreign key relationships here with some examples?
2 Answers
Use a has_many :through
association. Set it up manually.
Step 1: Generate your models separately. The joining model Study
will contain foreign keys, so remember to include the columns.
rails g model Course title:string
rails g model Student name:string
rails g model Study course_id:integer student_id:integer start_date:date grade:string
Step 2: Set up associations:
# models/course.rb
class Course
has_many :studies
has_many :students, through: :studies
end
# models/student.rb
class Student
has_many :studies
has_many :courses, through: :studies
end
# models/study.rb
class Study
belongs_to :course
belongs_to :student
end
Step 3: Run migrations, restart server (if necessary), and that's it. Rails will handle the rest.
Accessing attributes in the joining table may require careful timing to ensure the correct object is being accessed, since the joining object is not returned via Rails' built-in methods, ie @course.students
. Check out this answer for some ideas.
Read the guide for more information.

- 1
- 1

- 6,684
- 2
- 31
- 40
for many-to-many relationships use:
class Car < ActiveRecord::Base
has_and_belongs_to_many :tires
end
class Tire < ActiveRecord::Base
has_and_belongs_to_many :cars
end
Then you create a migration like this:
class CreateCarsAndTires < ActiveRecord::Migration
def change
create_table :cars do |t|
t.string :name
end
create_table :tires do |t|
t.string :something
end
create_table :cars_tires do |t|
t.belongs_to :car
t.belongs_to :tire
t.string :additional_dataA //optional
t.int :something_else //optional
end
end
end
It is very important that you name your join table in the migration in alphabetical order (c in cars comes before t for tires) as ActiveRecord will look in has_many_and_belongs_to relations for a table which is named this way pluralized-classA_pluralized_classB like apples_bananas vs bananas_apples which would not work and you would have to add the table name to your classes and it goes against the convention over configuration paradigm.
Hope it helps.

- 980
- 6
- 16
-
Thank you. That is a lot clearer. So do i understand correctly that i must create the model car and tire and then a third model called car_tire. As well as adding the associations in the models i should also modify the migrations with the 'belongs_to' association? – user3192316 Feb 06 '14 at 12:29
-
The reason i want to add the additional model is so i can add validation for the joining table. – user3192316 Feb 06 '14 at 13:19
-
I am sorry, for creating additional attributes the solution from gg_s is simpler to use. This way the associations are easier to use for you when adding the additional attributes. This way you get your migrations for free...(no hand coding). My bad. – Nikolai Manek Feb 06 '14 at 17:35