DEV Community

pjparham
pjparham

Posted on

Ruby on Rails relationships for models that join on multiple tables.

Ruby on Rails offers many tools to link models in your database, sometimes so many that it can be confusing to find the correct solution for your problem. I recently had two models, User and Image, that joined on two tables, Reviews and Favorites. Finding the right solution for this issue took some leg work, but eventually I implemented a clean solution that worked just as I needed it to. Keep reading if you too want to discover how to handle models that join on multiple tables.

The problem

I made a web app that had Users and Images. Users and Images both had many favorites and many reviews. Favorites are created when a user favorites an image, and reviews are created when a user reviews an image.

DB Layout

I needed both my users to both access what images they have liked and what images they have favorited, and the reciprocal for my images.

If I only had one joins table, I would achieve this relationship with the following code:

class User < ApplicationRecord
has_many :images, through: :reviews
Enter fullscreen mode Exit fullscreen mode

However, things start to look wrong when you add in the second relationship:

has_many :images, through: :reviews
has_many :images, through: :favorites
Enter fullscreen mode Exit fullscreen mode

The solution

Solving the above problem required me to search in a variety of places and was not the easiest to find, however the solution itself is very simple.

has_many :reviewed_images, :through => :reviews, :source => :image
has_many :favorite_images, :through => :favorites, :source => :image
Enter fullscreen mode Exit fullscreen mode

This allows me to access the necessary data easily.

Usage

Let's say I was playing around with this code in my Ruby console. If I set an instance of my user class equal to u1, I could call that user's favorite images with the syntax u1.favorite_images, and I could call their reviewed images with u1.reviewed_images. Pairing this access with my Controllers and Serializers, we can now send the nested data to the front end so our app operates the way we want it to.

Top comments (0)