The One-to-Many Relationship in Ruby

Claudia Borghini
3 min readJul 23, 2020

During my first week at Flatiron as a Software Engineering student, I was introduced to Object Oriented Programming, a very important topic, that can be a bit complicated for beginners.
I’d like to spend a few minutes explaining the One-to-Many relationship, with the hope that this article can help other new developers in the future.

If we consider Objects in Ruby like things in real life, we can easily see how they are related and connected to one another, and I will illustrate this relationship with an example.

A dog belongs to an owner: the dog has one owner, and the owner has a dog;
Another dog belongs to the same owner: this dog has one owner, and this owner now has 2 dogs.

Now, we can see how the owner is connected to many dogs: this is what we call a “One to Many Relationship”.

An owner has many dogs, and each dog belongs to that one owner.

In Ruby whatever belongs to something, is what it’s going to keep track of such relationship. So, when we say “A dog belongs to an owner” we know that the dog is what will keep track of the relationship with the owner.

Think about it: if the owner is a breeder, he/she will have many dogs, and it may be difficult to keep track of all of them. Wouldn’t it be easier if the dog was to keep track of the owner? It’s just one! How does the dog keep track of the owner? We can write the owner’s name on the dog’s collar. Great, so now the dog is keeping track of its owner, and the owner doesn’t have to remember every dog he/she has.

So what if the owner has a neighbor with as many dogs, and they all play together? How can an owner find his/her dogs? Well, it may sound long to do for a person (but it’s not for a computer!). The owner will check the collar of each dog, and will bring home just those dogs that have his/her name written on their collar.

Now let’s write this in Ruby code:

Let’s define the Dog class, with an attribute of a name. Notice that we will want to access a collection of all dogs that have been created, so we are creating a class variable @@all as an empty array. Every time we create a dog, we insert that dog instance in the collection of @@all dogs.
We are giving the dog also another attribute: the owner it belongs to, so that the dog can keep track of its owner.

class Dog
attr_reader :name, :owner
@@all = []
def initialize(name, owner)
@name = name
@owner = owner
@@all << self
end
def self.all
@@all
end
end

Let’s define the Owner class, with an attribute of a name as well.

class Owner
attr_reader :name
def initialize(name)
@name = name
end
end

We can now create a few dogs and the 2 owners who are neighbors:

fred = Owner.new("Fred")
barney = Owner.new("Barney")
dino = Dog.new("Dino", fred)
fido = Dog.new("Fido", fred)
snoopy = Dog.new("Snoopy", barney)

Dino belongs to Fred
Fido belongs to Fred
Snoopy belongs to Barney

So what happens when they all play together and Fred needs to quickly find his dogs and go home?
Fred will take all the dogs, and select only those for which the owner’s name is Fred.
Let’s define the following method in the Owner class:

def find_my_dogs
Dog.all.select do |dog|
dog.owner == self
end
end

We can now call this method on Fred to help him find his dogs:

fred.find_my_dogs#=> this will return an array of all the Dog objects( which have a name and an owner) for which the owner if Fred.[#<Dog:0x00007face70c0a80 @name="Dino", @owner=#<Owner:0x00007face70c0b48 @name="Fred">>, #<Dog:0x00007face70c09e0 @name="Fido", @owner=#<Owner:0x00007face70c0b48 @name="Fred">>]

and on Barney:

barney.find_my_dogs#=> [#<Dog:0x00007fa87d8850e0 @name="Snoopy", @owner=#<Owner:0x00007fa87d885298 @name="Barney">>]

This is the One to Many relationship, I hope this was useful!
Thanks for reading. Happy coding!

--

--