Modeling One-to-Many and Many-to-Many Relationships in Ruby

Mary Dick
4 min readOct 19, 2020

--

In our every-day life, we are constantly observing and coming in contact with the world around us. In observing and interacting with our environment, we are forming a new relationship through each interaction. Similarly, in object-oriented programming, objects form relationships with each other through interaction. As programmers, it’s our job to make sure that the relationships between objects are properly aligned to achieve the desired behavior.

In the last six weeks at Flatiron School, I have gained the ability to map out several different model structures in Ruby: one-to-many relationships and many-to-many relationships. We have gone through basic modeling, ActiveRecord modeling, and Ruby on Rails.

One-to-Many Modeling

In order to understand how a many-to-many relationship works, you must have a basic understanding of a one-to-many relationship. In this example, we have an artist and their songs. An artist writes many songs, and all of those songs belong to that single artist.

Created Using Excalidraw

To set this relationship up in Ruby, we create a class for artists and for songs. In the artist class, we use our attr_accessor to “get” and “set” our name method for the class. This makes it so that the user can both see and change the name of an artist. Then we set the parameters for initialization (name). This way, when creating a new artist instance, the user must input a name. Then we create a method called songs in which we select all song instances that belong to the artist (self), as well as a song_names method to list all of the artist’s songs by title.

In our song class, we initialize the title of the song as well as the artist instance that the song belongs to. We also create a class method, @@all, that contains an array of all Song instances. This will allow our Artist#songs method to function properly.

Now, we must write some test-data in a new file, main.rb, in order to confirm that the relationship was mapped out properly.

Once we have created instances of Song and Artist and associated them, we can test our methods!

When I run my main.rb file, the code should return all songs that belong to Jimi Hendrix and Billie Eilish.

And now you have a basic knowledge of one-to-many relationships in Ruby!

Many-to-Many Modeling

Now that you are able to create a basic one-to-many relationship, you can now try to model a many-to-many relationship.

In this example, we have a customer, a waiter, and a meal.

Created Using Excalidraw

Usually, when a customer comes to a restaurant, they order one meal and can have many waiters. A waiter serves many customers and serves each customer one meal. Therefore, the relationship between the waiter and the customer exists only through the meal; The meal joins the customer with the waiter.

In our Customer class, we follow many of the same steps as in a one-to-many relationship, but we also implement our joiner model (Meal) and add a few extra methods: Customer#meals and Customer#waiters. The helper method, Customer#meals, selects all meal instances that belong to the customer. The Customer#waiters method calls the meals method and returns all waiters that have served the customer.

Similarly, in the Waiter class, we write a helper method Waiter#meals that returns all meals that a waiter has served. Waiter#customers calls the meals method and returns all customers that the waiter has served a meal to.

Once the basic (and/or desired) methods are written, it’s time to test! In the main.rb file, we create instances of Waiter, Customer, and Meal.

Now that we have a few instances of each class, we can test our methods.

When we run main.rb, we should see a list of customers that Jenny and Tim have served and waiters that have served George and Rachel.

Conclusion

Once you are able to understand basic relationship modeling in ruby, the possibilities are endless! This skill transcends the bounds of a single language and can carry you through years of successful programming.

--

--