When I started learning Rails, I was extremely confused in associations. They are like a maze in which getting lost is easy.
Associations serve as link between models. They make performing operations on the records easier.
So, let’s take plunge into the details of Associations!
There are four types of associations.
- One-to-Many
- One-to-one
- Many-to-Many
- Polymorphic One-to-Many
- One-to-Many : One-to-Many is one of
the most commonly used association. It states that an instance of model has many instances of another model.
For example, A student is enrolled in a University but a University has many students.
We can say :
A Studentbelongs_to
a University.
A Universityhas_many
Students.
class Student < ApplicationRecord belongs_to :university end class University < ApplicationRecord has_many :students end
belongs_to
is usually on the other side of has_many or has_one relationship.Once we establish One-to-Many association, we get some very useful methods at our disposal:
university.students
: gives us all the students, enrolled in a university.student.university
: gives us the name of university student is enrolled in.university.students << student1
: adds student1 to the collection and returns the collection.university.students.delete(@student1)
: deletes student1 from the collection. Sets foreign key to null.university.students.destroy(@student1)
: removes @student1 from collection by running destroy on each object.university.students.build({ })
: instantiates a new student but does not save it.university.students.create({ })
: validates and creates a new student and saves it in the database.university.students.create!({})
: validates, creates and saves student in database, but returns the exception in case of failure.university.build_student
: instantiates a new student but does not save it.university.create_student
: creates a new student and saves it in the database.
- One-to-One : One-to-One
association states that one instance of model contains exactly one instance of other model.
What that means is, for example: A student has one University Account. One University Account belongs to one Student
We can say:
A studenthas_one
Account
An Accountbelongs_to
a Student
class Student < ApplicationRecord has_one :account end class Account < ApplicationRecord belongs_to :student end
After the relation is established, in One-to-One as well we get few useful methods:student.account
: gets the account details for the student.student.build_account
: instantiates the new account but does not save it.student.create_adress
: validates, creates and saves new address to the database.
-
Many-to-Many : This association says that many instances of model has many instances of another model. It needs a join table which stores the relation between the two models.
It can be set up in two ways :
a) Has_And_Belongs_To_Many (HABTM): In case of Has And Belongs To Many , lets take an example and say, Teachers teach many Students and Students are taught by many Teachers. We can say it as :
Teacherhas_and_belongs_to_many
Students
Studenthas_and_belongs_to_many
TeachersIn this case the join table name by default will be
students_teachers
, but can be customized by the programmer.
class Teacher < ApplicationRecord has_and_belongs_to_many :students end class Student < ApplicationRecord has_and_belongs_to_many :teachers end
Now, with the establishment of HABTM relation, we get another set of methods to play around with:
student.teachers
: all teachers teaching a particular studentstudent.teacher_ids
: returns ids from the colectionstudent.teacher_ids = [1, 2, 3]
: creates collection with objects corresponding to PK values supplied.student.teachers.delete(teacher_1)
orstudent.teachers.destroy(teacher_1)
: deletes or destroys the relations for teacher_1teachers.empty?
: checks if teachers contains datateachers.size
: checks the size of teachers collectionstudent.teachers.create(attributes = {})
: creates and adds objects to the collection.
HABTM is an approach which looks easy, but it is very rigid in the sense that we gain almost no flexibility of working with the relationship model. This problem is solved using Has Many Through relation.
b) Has Many Through : Has Many Through is a more flexible approach under many_to_many relation. Let’s say that Students in a university are to be sent many reminders for events and each event has many students attending it.
We can say:
Studentshas_many
Remindersthrough
StudentsReminder
Remindershas_many
Studentsthrough
StudentsReminder
StudentsReminderbelongs_to
Students and Reminders
class Student < ApplicationRecord has_many :students_reminders has_many :reminders, through: :students_reminders end class StudentsReminder < ApplicationRecord belongs_to :students belongs_to :reminders end class Reminder < ApplicationRecord has_many :students_reminders has_many :students, through: :students_reminders end
Has Many Through is a more flexible approach because now we can work with StudentsReminder model as well.
- Polymorphic One-to-Many: In Polymorphic association, the model belongs to more than one other models,
on a single association. For example, a photo model can belong to either Student or Teacher.
class Photo < ApplicationRecord belongs_to :identification, polymorphic: true end class Student < ApplicationRecord has_many :photos, as: :identification end class Teacher < ApplicationRecord has_many :photos, as: :identification end
While setting up Polymorphic Association we must declare Foregin Key column and a Type column in the Photos model.Now, that we are done with setting up , we can go ahead and access the photos belonging to students and teachers.
From an instance of Student we can say,@student.photos
.
And, from an instance of Teacher model,@teacher.photos
.How amazing is that!