Object Associations in Ruby

(and why the term “single source of truth” can be confusing)

magreen118
5 min readJul 4, 2020

One of the coolest things about object oriented programming is that you can build things that reflect the real world (booleans are useful, but try explaining them to a friend who doesn’t know how to program).

If you want to build an instrument class for example, you can intuitively figure out what attributes you might want to give it:

Creating an instrument class

When a class is thoughtfully crafted, instances of the class share traits with the real-world things they’ve been modeled after:

Instrument instances

It’s really exciting to realize that you have the power to create anything you want, exactly how you want:

Hopefully you’ll put this to better use than Jafar intended to.

Object Association

The ability to build individual objects is powerful, but we’re limited in what we can do if they aren’t able to interact — enter object association!

Trying to wrap your head around relationships can be tough when you consider the complex webs of associations present in apps you use every day. In order to eventually understand more complex examples, it’s helpful to break relationships down into their most basic components. I’m going discuss two basic relationships: one-to-many and many-to-many.

One to many (has many / belongs to)

“One to many” associations refer to situations where a single object of one type is associated with many objects of another type. I’ve found it extremely helpful to draw relationships to better visualize whats going on:

One to many
(The single line always goes towards the “one” and the 3 lines always go towards the “many”)

We could add a Musician class to our original example to represent this kind of relationship.

For the purposes of this example, let’s imagine Prince, Stevie Wonder, and David Bowie formed a super group. They’re all talented so each musician can play multiple instruments but they also have big egos so they don’t want their bandmates to compete with them (so each instrument can only be played by a single musician). In this example we’d say that each musician has many instruments and each instrument belongs to one musician.

Musician has many instruments

We would then need to adjust the Instrument class to reflect how the objects can be related:

one to many in code

Each instrument can now be associated to a single musician by taking a musician instance as an attribute. Below are some examples of how instances would interact:

musician instances

We associate the objects this way so that all information about how they are related is stored in one place (with the objects that are the “many”). This is called maintaining a “Single Source of Truth.” The benefit of this is that we don’t have to maintain accurate data in multiple places (like having both classes keep an array of instances of each other). More on this later…

Many to Many

“Many to many” associations refer to situations where a multiple objects of one type are related to multiple objects of another type. In order to accurately reflect this, we need what’s called a “join class.”

many to many

Going back to our previous example, let’s now assume that the super group has gotten over their egos and now allow each other to share instruments. This now means that each musician can be associated with many instruments and each instrument can be associated with many musicians. In order to deal with this, I’ve created a join class called song:

many to many in code

The join class takes instances of each of the non-join classes. This allows it to function as the “Single Source of Truth” for information about how musician and instrument instances relate to each other.

musician song instrument: many to many

Why “Single Source of Truth” can be a confusing term

I found the idea of a single source of truth a little confusing when I first learned it. This is because there are actually multiple single sources of truth in scenarios where objects are associated.

The single source of truth (SSOT) is different based on the context of the information you’re looking for. If for example, we wanted to know how many instruments a musician plays, the SSOT would come from the Song.all method (which returns an array of all instances where an instrument and musician are associated).

However, now let’s imagine a situation where the group receives a donation of a xylophone even though no one knows how to play it.

lonely xylophone

If we want to look up how many total instruments have been created Song.all isn’t sufficient because it doesn’t know about the xylophone instance (it only knows about times that musicians and instruments are associated). To find the total number of instruments, we would look to Instrument.all as the SSOT for this particular prompt. It keeps track of all individual instances of an instrument, whether they’re related to a musician or not.

The key thing to remember is that just because objects can be associated doesn’t mean that they have to be. In order to build helpful and interesting methods, you need to be clear on what the SSOT is for the information you’re looking for.

Final Thoughts

Figuring out object relationships can be intimidating so don’t be discouraged if it takes you a bit to really get it down. Remembering to break associations down into smaller components and to be clear on the context of the information you’re looking for can be really helpful in understanding them better.

--

--