Ruby’s (Next Top) Domain Model
After learning how to create methods, enumerate through hashes, arrays, arrays of hashes and hashes of arrays *deep breath*…
We then began learning how to create a class. A class is a Ruby object that is used as a blueprint to create more objects that are instances of that class. A class holds attributes about itself that we’d like to know. For example, a Pet class would hold attributes about its name, breed or any other information that we’d like our Pet objects to have. An Owner class would hold attributes about its name, age, and any other information about the Owner.
This was the moment, I believe, that everything I learned started to sound like something applicable to real life. Though, in real life, relationships exists between objects. An Owner and a Pet would have a relationship with each other. A Book and an Author would have a relationship with each other. A Customer and a Waiter would have a relationship with each other. A Person and a Passport would have a relationship. Relationships are everywhere!
Luckily, there is a way to represent these relationships in Ruby. You can turn these real world objects into ruby class objects. A relationship can exist if one of the classes holds an attribute that references the other class’s instance.
There are many types of relationships between classes, I will be discussing the one to many and many to many relationships:
One to many relationships(has-many/belongs-to)
When we describe the relationship between a pet and an owner, it goes like this:
A pet belongs to an owner. An owner can have many pets. When you see a pet, it usually has a collar with its owner’s name and/or address. When you see a pet owner, they will not have a tag with the name(s) of their pet(s).
The class on the right side (the one with several arrows pointing at at, belongs to the class on the left side (the one that has the base of the arrow) has many of the class on the right.
With these scheme, any class that belongs to a different class would hold an attribute that is an instance of the other class.
The pet would hold an attribute with its owner’s instance.
Pet is responsible for knowing who its owner is.
An owner would know who its owner is by looking for a pet instance who’s owner attribute is equal to the owner’s instance.
Many to many relationships(has many through)
Now imagine the relationship between a Customer and a Waiter. Logically, a Customer can have many waiters, they are not restricted to one. A Waiter would also have many customers they have to wait on. So let’s draw it out!
Here we have our arrows pointing at each other. Neither class is really on the receiving side of the arrows.
This is situation with arrows pointing at each other is not allowed in our schema, so we need to create a class that will be on the receiving end of the arrows. What links a Customer to a Waiter and a Waiter to a Customer??
A Meal of course! We will create a Meal to be our joining class. The Meal’s attributes would be the meal name, the customer who ordered it, and the waiter who’s serving it. Let get started!
In this schema:
Customer has many Meals…and…Meal belongs to Customer.
Customer has many Waiters through Meal.
Waiter has many Meals…and…Meal belongs to Waiter.
Waiter has many Customers through Meal.
The “has many through” relationship links the Waiter and Customer class together! Let’s write out our code!
The Customer and Waiter classes only need to keep track of their own attributes. Like a name and an age. They are responsible for knowing who they are, respectively.
The meal, on the other hand, would keep track of the attributes of the customer, the waiter, and its name (steak/soup).
I enjoy drawing out relationships. I think it makes your coding 100x easier when you can visualize who belongs to what and who has many of something or if a joining class is needed to be made.
Try it out! Draw out some relationship schemas that you’re curious about!