Most confusing words class_name, foreign_key and source in Ruby on rails Relationship
Table of contents
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
PermalinkLet'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 :)
Permalinksource
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 :)