Object Relationships in Ruby: The Baseball Example (or the ‘Anything But Pets’ Example)

Ori Markowitz
5 min readDec 3, 2020

--

Object-oriented programming allows us to build relationships between objects, and then act on those relationships, which makes it ideal for modeling real-life situations. Ruby is a very popular programming language due in part to its adaptability to our world and the way relationships can be represented in its object-oriented environment.

Given the above, it’s sort of odd how so many examples of object relationships in Ruby revolve around pets and their owners.

Photo by Jamie Street on Unsplash

Owning pets is absolutely day-brightening, but a lot of us don’t own pets. And even if we did, there are more than enough pet examples in Ruby explanations to hold everyone over for awhile.

So let’s try something new.

Photo by Mike Bowman on Unsplash

Some of the key relationships you’ll encounter in your Ruby journey are the “Has Many/Belongs To” and “Has Many Through” relationships.

Has Many/Belongs To

Let’s say we were working on an application that handled the roster information for a professional baseball team, the New York Yankees. Aaron Judge, the best player on the Yankees, knows his Manager is Aaron Boone. And why wouldn’t he? He only has one manager! Boone on the other hand manages many players, including Gleyber Torres and Gerrit Cole, which can get confusing. How can we keep track of these relationships while maintaining a Single Source of Truth?

Well, we know that Aaron Boone manages many players, so you could say that Boone has many players.

Aaron Boone

We also know that a player, like Aaron Judge, has one manager, meaning that a player belongs to a manager.

Let’s implement this relationship structure in Ruby by building two classes: Manager and Player.

Manager Class
Player Class

A Manager is instantiated with a name, number, and team, yet no reference to any of the players they manage. This is because the Player, the belongs to object, holds the reference to their Manager.

We can create Aaron Boone as a Manager instance:

Manager Instance

A Player is instantiated with a name, number, type, position, age, and manager. When we create a new Player, like we do with Judge and Cole below, we make sure to pass in a Manager instance object as the manager. This way, a Player instance can know about its manager and belong to it.

Player Instances

If Boone wanted to know all the names of the players he manages, it wouldn’t matter that there’s no reference to his players anywhere, because he could use his relationship with the players to find out.

We could write an instance method #player_names in the Manager class that returns all the players Aaron Boone manages:

#player_names

Has Many Through

In baseball, not all players are the same type. Some baseball players are position players, and others are pitchers. In Ruby-speak, this can be broken down into a player belongs to a type, and a type has many players. So continuing along with our original relationship, we can say that a player belongs to a type and a manager, and a manager has many types through players.

In our app, we’ll define a Ruby class called Type.

Type Class

Types are instantiated with a name, and a key stat that’s most associated with that player type.

Type Instances

When we create our Player instances again, we pass in a Type object instance for the type argument. The Player instances now hold the reference to both objects they belong to.

Player Instances

Now, if Aaron Boone wanted to know all the player Types he manages, he can ask the Players who belong to him to ask about the Types those players belong to. In simpler terms, Boone, the Manager, has many Types, through the Players.

We can write an instance method #player_types in the Manager class to return all the player types Aaron Boone manages:

#player_types
Has Many Through

Conclusion

Ruby allows us to model real-world scenarios using object-oriented programming and object relationships. The Has Many/Belongs To and Has Many Through relationships are two of the most common, but by no means the only ones. Still, it’s crucial to your Ruby and overall programming journey to get familiar with these relationships and how they work. If you were looking for a detailed write-up that didn’t use pets as an example, then I hope you found it here. Either way, I hope it was informative. Play ball!

--

--