DEV Community

Sana Mohiuddin
Sana Mohiuddin

Posted on

Relationships in Rails

Databases are an integral part of making most dynamic applications functional. When you log into Instagram or Snapchat, your specific information is what populates your screen. Your username, your photos, your feed filled with images from individuals that you follow; none of that would be possible without databases. They store all that information, which later populates the application's interface with the necessary data. For our examples, assume we are working with a stack that consists of a ReactJS frontend, a Ruby on Rails API that utilizes a PostgreSQL database. The API is the middle man that allows communication between the frontend and the database.

Why are Database Relationships Important?

Now that we have a bit of an overview of why databases are important to make your application work the way it should, let's discuss relationships between the different models in a database. Let us once again use the Instagram example. We have a user model and photo model. Each user has many photos that they have posted on their account. Each photo belongs to the user who posted the photo. It is important to define those relationships, because Rails gives us many tools to use those relationships to access your data more efficiently.

One-To-Many Relationship

The user to photo relationship is an example of a one-to-many relationship. Here is what we can type in the terminal to generate a user model:

rails g model User username:string bio:text age:integer
Enter fullscreen mode Exit fullscreen mode

This is a simple model with three attributes that define a user. Now to generate the photo model we can type this:

rails g model Photo image_url:text caption:text user_id:integer
Enter fullscreen mode Exit fullscreen mode

You may be wondering what the user_id attribute is for. It is known as a foreign key and it allows us to associate each photo with the correct user. When each instance of a user is created an id is automatically made, so when a new photo is posted by a user, their id will be saved in the new instance for that photo. We need to take one more step to get the full access to what Rails provides us.

class Photo < ApplicationRecord
  belongs_to :user
end

class User < ApplicationRecord
  has_many :photos
end
Enter fullscreen mode Exit fullscreen mode

The belongs_to and has_many macros are the last step we need to finalize the relationship between the two models. Now we can do things like this:

user = User.first
user.photos
#will return all photos that belong to that user
Enter fullscreen mode Exit fullscreen mode

The first line of code above gets us the first instance of a User and saves it in the user variable. You can then chain .photos to that user to return all the photos that were posted by that specific user. Rails allows us to retrieve all those photos quickly and efficiently instead of getting all the photo instances and finding all the ones with the matching user_id. Makes it much simpler for us coders, so we can focus on more complicated parts of our code instead of the simpler things. You can also find the user associated with each photo in a similar way.

photo = Photo.first
photo.user
#will return the user that owns that photo
Enter fullscreen mode Exit fullscreen mode

This code will find the user that posted that photo and return it. This is a quick summary of a one-to-many relationship, and how to instantiate it in Ruby.

Many-To-Many Relationship

Now let's think of an example to highlight a many-to-many relationship. If we had an application where a student can join clubs and catch up with club news. We could have two model students and clubs. A student can be in many clubs, a club can have many students in it. In rails in order to create a many-to-many relationship between these two, we would need a joins table. To create a joins table we would do the following:

rails g model StudentClub student_id:integer club_id:integer
Enter fullscreen mode Exit fullscreen mode

This table's only job is store the the foreign keys for the student and club so rails can do the heavy lifting and create those associations for us. It is important to pay attention to syntax when creating the join table. It must be a combination of the two model names, as shown above. Now we must add the correct macros in the model files.

class StudentClub < ApplicationRecord
  belongs_to :student
  belongs_to :club
end

class Student < ApplicationRecord
  has_many :student_clubs
  has_many :clubs, through: :student_clubs
end

class Club < ApplicationRecord
  has_many :student_clubs
  has_many :students, through: :student_clubs
end
Enter fullscreen mode Exit fullscreen mode

Once you have added the above code to your files you are able to do the following:

student = Student.first
club = Club.first
student.clubs
#will return all clubs student is apart of
club.students
#will return all student in the club
Enter fullscreen mode Exit fullscreen mode

Make sure to pay attention to the syntax for everything because Rails needs that to make the associations work properly.

One-To-One Relationship

The last relationship that will be discussed is a one-to-one relationship. This particular relationship probably won't be used as much as the last two, but it is still important to know. The example that will be used is the relationship between a state and its capital city. A state has one capital city and a capital city belongs to that state. The relationship can be defined with the following code:

class State < ApplicationRecord
  has_one :capital
end

class Capital < ApplicationRecord
  belongs_to :state
end
Enter fullscreen mode Exit fullscreen mode

You can then access the associated information in the ways we demonstrated earlier.

Conclusion

The three relationships we discussed above are very important to understand in order to properly define your database in a way that works efficiently.

Resources

Top comments (0)