I know what you might be thinking, “This is not the relationship advice I was looking for…” Well, you are right, this isn’t about mending or developing those lifelong bonds with your friend Ruby. We are talking about Ruby’s class relationships. I am going to do a high-level walkthrough highlighting the process of building object-oriented class relationships and creating a database schema for a relational database for a ruby built project. We aren’t going to go too deep into the code, but rather focus on the process to follow that can help you solidify the relationship concepts needed to build your project’s foundation.
NOTE: This article assumes you have a working knowledge of Ruby, Object-oriented programming, SQL, and understand the basics of Active Record or Object Relational Mapping.
Before we begin drafting and talking about these relationships, let’s define a few core terms covered later regarding object-oriented programming:
- Class: A class is a blueprint that defines and creates a thing or object.
- Object: “Everything in Ruby is an object.” An object represent’s a thing, that has attributes and behaviors.
- Instance/Instantiate: An instance is an occurrence of an object that has it’s attributes and it’s behaviors defined and created. The process of bringing this object to life is called instantiation. Example: A class named dog creates an instance of a dog named “Bowie” that has attributes like white and brown fur, and doesn’t bark.
- Methods: The behaviors(functions) of a given object. There are instance methods to define behaviors of a particular instance of an object and there are class methods that can apply to the class itself or all instances of that class.
- Schema: A Schema is a programmatic way of defining the construction and datatypes of your database. These are like the columns and rows in a spreadsheet, as well as the name and relationships that are between those spreadsheets.
- Database: A database is a structured set of data where we store persisting information from the instances of objects.
- Class Relationships: Class relationships are the way classes and object attributes relate and interact with each other. This is the process of This is through a has many, belongs-to, has many through, many to many relationships, and more.
- THINK ABOUT IT Before we start jotting down or drawing out our relationships, we usually want to start with understanding the problem that building our app is trying to solve. Then, we can think about how we want our app to behave and develop a list of deliverables or tasks to build the app.
I recommend writing out the following questions to answer:
- What problem are we trying to solve?
- What actions or behaviors are involved in solving this problem?
- What are the things we want to be represented in the app as classes or things and what are their relationships with one another? This should tell us about what classes and objects we are dealing with and how they interact will interact with one another in the project.
Writing these down will help put guideposts in your thought process when identifying why you are trying to build this app and how you are going to approach building class/object relationships and storing information. Also, at this point, you should start to think about the things(classes), their attributes, and their relationships.
2. Draw it out Get a piece of paper, or an app like draw.io or lucidchart, or a sharpie and a white desk :), and draw out the associations between the things(classes) that pertain to each other. This is the most important part. Creating a visual representation goes miles when conceptualizing and processing (in your head) how your app will work. This also reveals the various models you will be building along with how to code the newly created associations in your app.
3. Code: Write your models, classes, and methods! At this point, you should have an idea about why you are building this, what classes need to be created, and the relationships of how they work together.
4. Code: Active Record Build out the framework for your relationships using the Active Record macro. It isn’t magic, but close to it.
5. Code: Create a database and write your schema By now, you have created classes, you know what classes and objects will interact with each other, the attributes each class has and you can play around with creating instances of real data utilizing ‘binding.pry’ or ‘rake console’. The next step is saving all this data in an organized and structured way to your database.
If we aren’t organized in our process, we might wind up with a drawing or diagram looking like this:
To not go too wild creating a complicated map of getting mail to office employees and finding out there is no Carol, let’s jump in and complete an example. Since this example is fresh in my mind from my first project at Flatiron, we are going to build a COVID Tracer app.
- THINK ABOUT IT
What problem are we trying to solve?
Right now, I have no idea who of my friends or family members have received COVID tests, when they have hung out with each other or myself, and if they possibly exposed the virus to one another.
What actions or behaviors are involved in solving this problem?
I need to create an app that records a user’s basic information (name, email, etc), information about tests they have taken, and information about who they have exposed themselves to.
Be succinct and try to identify the keywords when writing this, you will notice these keywords that come out of your statement in trying to identify what actions or behaviors are needed to make your app work.
What are the things we want to be represented in the app as classes and what are their relationships with each other?
You are seeing a bit of this with the last question that was answered. We see there are models for the User, Test, and Exposure. To aid in resolving some ambiguity let’s think of Exposure as a way to submit a report of exposing friends or family members to COVID.
Build relationships: Well, we probably want our users to have many tests, and that means our tests belong to users. Our users will have many exposure reports through the tests that are found positive. Therefore, our tests belong to exposure reports, which are needed to know if those exposing others are infected.
I will admit, this example is tough. That is why I am writing about it. I think it is super important to nail down the understanding of these relationships and get why for example users have many tests. Take the real-life example for what it is, that is what makes object-orientated programming so awesome. It represents real things and real interactions. What I learned, is that you will be refactoring a lot if you don’t get the foundation of this right and solid you can see that in my project for sure.
2. Draw it out
Draw out the relationships, and map out the table of attributes you will save! Let’s draw.
And there we have it! We have a visual representation of the basic relationships we need to start building our app. Now that we have the relationships conceptualized, we have the attributes of each object or class which we can use to build out our DB schema creation, and we have the name of each class. Now we can start building our app.
3.Code: Write your models, classes, and methods!
Here is the file structure I used in my project at Flatiron. This is an Active Record template the school provided that I built upon. You can find my project code here and see what I am discussing here.
You’ll go into your app folder and build out your models(classes). Navigate to that folder to create files for each class. User.rb, Test.rb, and Exposure.rb. Isn’t it so easy now since we made the diagram!
4. Code: Active Record
Next, we’ll write up the relationships in each class. Please reference ActiveRecords documentation on the macro you will be writing. It should look something like this.
This is how ActiveRecord will maintain the Primary Key-Foreign Key association between your tables. This is how you are granting your classes access to the instances(persisted data) between the tables you are going to create.
For example, if I want to find the tests of a user at some point I can do something like this:
User.find_by(email:email).tests This is because you told ActiveRecord, User has many tests.
5. Code: Create a database and write your schema
Next, we will use the
rake db:create command to create a database and then
rake db:create_migration NAME="create_users_table” to create a migration file for building out our tables and adding columns.
Rake is a task and dependencies management tool. You can read more here. If you have your rake file all set up properly, you can navigate to it and see the required gems or library that is used to populate your rake commands. You might see something like
require 'sinatra/activerecord/rake' Meaning you get these rake commands from the Sinatra ActiveRecord gem. You can find that documentation here. To see all the rake commands, just type in
rake -T to view them. You will see more about what I am referring to here.
This create_migration task creates a file in our migrate folder where you can find a class that has the name like
class CreateUsersTable < ActiveRecord::Migration[x.x] . This is where we will add our code to create our tables. For our users table and columns, we’ll do something like this:
Lastly, we will run the rake task
rake db:migrate. This command will action creating the table with the columns I have told rake to do.
You can now navigate to your schema file, which will tell you about how your database is constructed. It will look something like this:
That’s it! We did it.
We started with a problem, we answered some questions on why we wanted to build our app to solve this problem, we broke down the objects/classes and their relationships, we made an organized diagram of our app’s schema and then built our database with relationships in our app. Now we have a process that can be repeated to develop a foundation for our projects in the future to build some awesome apps.
I hope this was helpful and kinda fun. Please share any feedback, and thanks for reading!