One-to(o?)-Many — An Introduction (Ruby)

Photo by Laura Ockel on Unsplash

Relationships can be tricky. Human and tech ones. However, what would we — and Ruby — be without them?

As an Object-Oriented Programming language (OOP language), Ruby does love, or, require its objects and everything that comes with it in order to function. Basically, as you already know by this stage, everything in Ruby is an object, and every object (also called instance) belongs to a class. The class leads to its objects having a state and certain behaviours. And classes can have relationships with each other, which is helping us Developers to do our beloved domain modelling.

There are different types of relationships, but for now we will focus on Ruby’s One-to-Many relationship. In this concept we are talking about classes which are connected to each other through and . In order to grasp this connection (relationship) better, we are going to create a simple application for the HR Department of a small bank, focusing on very simplified data of the company and its employees in order to receive some generic information.

How are we going to approach building this application though?

Think about the necessary classes and their relationships

We have to build the relationship between the company and its employees. In this case, we are creating two classes: Bank & Employee (the names of classes always start with capital letters when you are writing your code). While the bank has employees, an employee only one company (the bank). For the sake of simplifying the explanation of the concept, we are disregarding freelancers or part-time employees who might work for more than one company at the same time. Here we assume that our employee is employed by this one bank only.

Map out an Entity Relationship Diagram (ERD)

So again, the company has many employees, and the employee belongs to the company. Creating an ERD — which is highly recommended for working with classes — the relationship would look like this:

My ERD for the Bank class and Employee class

Clarify the class state and behaviours

Now we need to think about what we want our classes to be capable of, and how to make them interact with each other. In more technical terms, we need to think about the state and behaviour we are going to give our class instances (objects of the respective class), and how to make the One-to-Many relationship work through code.

Before we are writing a single line of actual code though, let us map out what our classes need to contain via some pseudo-coding (describing what the code will have to do in a more natural, easy to understand language — this is also very helpful if you are looking back at your code after a while and are wondering what you attempted with it in first place).

class Bank# Get location
# Create new branch with its location
# Get list of all employees of Bank
# Get list of employees of Bank per specific location
end
class Employee
# Get employee name, job title and location
# Create new employee with the name, job title and location and save the employee (instance)
# Be able to change employee name, job title and location
# Get all employees
end

Side note 1: Each class would be created in a separate ruby file.

Code, code, code…

The next step is to write the code for the respective state and behaviours we outlined — keeping in mind that we want our Bank class as the parent class to take care of most actions, while we are leaving the Employee class (child) as generic as possible.

Since the child class, which belongs to the parent class, needs to know about this relationship and is responsible for knowing, we have to create a connection, in this case created through . Taking above outlined pseudo-code and the relationship into account, I have created the following simple methods for both classes:

Bank class
Employee class
  1. attr_reader: This allows us to get the
  2. initialize(location): This allows us to create a new instance, accepting as an argument
  3. self.employees: This allows us to ask Ruby for an overview of all instances of employees of the Bank (and to get the information)
  4. employees_location: This allows us to ask Ruby for an overview of all instances of employees of the Bank working in the location of the object it’s called on (and to get the information)
  5. attr_accessor: This allows us to get and set the , and
  6. @@all: This allows us to have a place (an array) to store all the created Employee instances in
  7. initialize(name, job_title, location): This allows us to create a new instance, accepting , and as an argument and immediately save this instance to @@all
  8. self.all: This allows us to ask Ruby for the array of the saved instances of Employee (and to get the information)

…and don’t forget to test

All looks good? Last, but not least, let us do some testing to see if we are receiving the data we want to receive — and to make sure that our One-to-Many relationship is working the way we want it to work.

Side note 2: We should be testing all the time in order to spot and fix errors as soon as possible, and not only in the end of course.

We are now creating example data in order to test our classes, methods and relationship:

If we are running the method on object we should only get back the three employees , and . Let’s check by typing the following into the terminal (using pry) and press return:

b2.employees_location

We made it! The method returned what we wanted it to return! Feel free to test the other methods as well — it all did work for me.

We have successfully created the One-to-Many relationship between the Bank and its Employee(s) and received data through a method of one class which is resulting in Ruby returning instances created by the other class.

Relationships might not be so tricky after all…!

(she/her) ➳ Software Engineer ♡ People Advocate