Most confusing words class_name, foreign_key and source in Ruby on rails Relationship

Most confusing words class_name, foreign_key and source in Ruby on rails Relationship

When I was learning Ruby on Rails relationship I gone through one-to-one, one-to-many and many-to-many types from official rails guide. I found it very easy but when I started creating my first rails app by following Book by Michael Hartl (Ruby on Rails Tutorial) I came across these key words (class_name, foreign_key, source) and I found it very difficult at that time. After so much googling and experiment I finally understood use of all these keywords

Let's start with class_name and foreign_key

Suppose I have two model

1) school_class and 2) student,

Definition : school_class have many student and student belong to only one school_class

before jump to class_name and foreign_key we need to understand below things,

# SchoolClass Model
class SchoolClass < ApplicationRecord
   has_many :students
end
# Student Model
class Student < ApplicationRecord
  belong_to :school_class
end

There is one column called school_class_id in Student Table

NOTE : by @class_name is represent instance variable of that class

when I say @student.school_class rails search for column name school_class_id in "student" table and then find "SchoolClass" object with that id.

When I write @school_class.students then rails go and search for column name school_class_id in student table and use it to find all students objects.

Now lets use some creative name for association,

1) I want @school.all_students instead of @school.students 2) I want @student.my_class instead of @student.school_class

# SchoolClass Model
class SchoolClass < ApplicationRecord
   has_many :all_students, class_name: :student, foreign_key: 'school_class_id'
end
# Student Model
class Student < ApplicationRecord
  belong_to :my_class, class_name: :school_class, foreign_key: 'school_class_id' 
end

when I run @student.my_class then rails go for column name school_class_id and use that value to find object of "school_class"

Same for @school_class.all_students, rails go for column school_class_id in "student" table

By default Rails use class name to find foreign_key and table for searching, but if we want to use different foreign_key or table name then we need to specify it as foreign_key and class_name :)

source

source is similar to class_name but scope is used only when we have has_many_through relationship

Ex :

# student model
class Student < ApplicationRecord
 has_many :subjects
 has_many :teachers, through: :subjects
end
# subject model
class Subject < ApplicationRecord
 belong_to :student
 belong_to :teacher
end
# teacher model
class Teacher < ApplicationRecord
 has_many :subjects
 has_many :students, through: :subjects
end

Now let's say @student.teachers, so rails use subject model(we mention "subject" as through) and from subject model it will use teacher association to collect all objects. Same logic apply for @teacher.students

let's use some creative name for association, 1) @student.my_teachers Instead of @student.teachers

# student model
class Student < ApplicationRecord
 has_many :subjects
 has_many :my_teachers, through: :subjects, source: :teacher
end
# subject model
class Subject < ApplicationRecord
 belong_to :student
 belong_to :teacher
end
# teacher model
class Teacher < ApplicationRecord
 has_many :subjects
 has_many :students, through: :subjects
end

we have added source in student model as you can see.

So when I say @student.my_teachers then rails use subject model(we mention "subject" as through) and from subject model it will use teacher association(if we not provide teacher as source then it will try to use my_teacher association of subject class) to collect all objects.

Thanks for reading my first post on Hashnode :)