0

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?

Dave Newton
  • 158,873
  • 26
  • 254
  • 302

2 Answers2

0

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.

Community
  • 1
  • 1
Substantial
  • 6,684
  • 2
  • 31
  • 40
0

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.

Nikolai Manek
  • 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