Recently I had to set up a ruby project with Active Record associations and I found myself struggling to piece everything together.I’ve decided to write this blog post to guide you through the setup process and give you a quick overview of model associations.
The world is full of relationships we can represent using associations. Think, pets and owners, restaurants and customers, patients and doctors, etc. Luckily for us,we can model these relationships with Active Record associations.
One of the most common rails associations is the has_many association. When you see has_many, think about whether that one thing can have/own many other things. This association represents a one to many association.
Take a minute to think about the following relationship examples:
- An author can have many books
- A user can have many twitter posts
- An owner can have many pets
The has_many relationship exists to help you model these relationships. When in doubt, just think about whether that specific thing, whatever that may be, can be the owner, have many other things. The naming convention on this association is plural (has_many :appointments).
When you’re brainstorming your application and user interaction you may realize that one of your models can be related to many others through an intermediary. Think about the following examples:
- A physician has many patients through appointments
- A chef can have many customers through the waiter
- A lyft driver can have many customers through the app
- A pet owner can be related to many vets through it's pet
In all of these examples,a connection exists through a pass through model (waiter, pet, appointments). This represents a
has many_through association because we're using a third third model to join them. The naming on this association is plural(has_many :patients, through: :appointments).
This association is for models where a one to one connection with another model exists.In other words, one instance of this model must be directly related to it's parent model through a foreign key. This model declaration is singular (belongs_to :Physician). This association It's commonly used in one to many and many to many relationships. Consider the following examples:
- Posts belong to users
- Pets belong to owners
- Appointments belong to physicians and patients
That's all on associations for now, If you'd like to dive into rails associations, see the docs here.
For the remainder of this post, we’ll be implementing a many to many relationship between physicians and patients, seeding them with some data, and looking at some quick examples of how to access data. Let's start by setting up our environment and our migrations.
Our development environment looks like the file tree above. If you wanna follow along, you can download the project folder here.
We can get started and create our migrations. We can do this with the useful command
rake db:create_migration NAME=migration_name. We can do this to create three empty migration templates inside our migration folder. We'll then define our table schemas.
Now that we’ve set up our table schema, let’s migrate with :
Once we’re done migrating, our schema file will be populated. Now you can refer to your schema if you need a quick reminder of the table layouts.
If you need to make a change to your tables, you can rollback with
rake db:rollback, make your changes in the respestive migration files and migrate again.
At this point, we must head over to our models folder and set up our relationships. Let’s create three files for our models. If you’re using vscode with the code path set, you can just type
code physician.rb appointment.rb patient.rb to get three titled files we can use.
We will be setting up a has_many_through association. In our association, physicians will have many patients through appointments.
You will notice that our appointments model, reprents the belongs_to association and holds the patient_id and physician_id foreign keys.
Because these associations allow us to inherit a lot of commonly used methods from Active Record. Need to delete, update, find, an instance? There’s a method for that. Yay!.
We’ve come a long way. Let’s make sure our associations are working properly. In order to add some dummy data quickly, I created a seeds.rb file under our db folder and used the faker gem to quickly seed our project with 10 physicians, 10 patients, and 11 appointment instances. This is a small snapshot of what our current tables look like now.
The snapshots above are what you would get by running the name of the model + .all inside a PRY session on your environment. At this point, we have some data, so we can test our relationships. We can select any physician or patient instance and call on appointments to get a list of their appointments and/or corresponding physicians/patients.
Physician.first.appointments would select the first physician instance of the physicians array and display their appointments in the appointments tables as seen above.
In the example above, to see the a patient's name, we simply access the desired instance and then access the patient. To see the second appointment's patient instance, we type
Need the appointment time? use
I won’t show the patient example, but it would work exactly the same, except that you would substitute physician for patient.
This works like magic! Yay! We’ve confirmed that our relationships are set up correctly. Our physicians know about their appointment times and their patients, and our patients know about their appointment times and physicians. Did you notice we didn’t build any methods from scratch? That's the Active Record magic! And it’s the reason understanding relationship associations is so important. It just makes life easy and allows you to spend your time coding the hard stuff.
That is all for now, but if you’d like to deep dive into associations, I recommend you go through the Active Record Associations docs here.
If you've made it this far, you deserve a virtual cookie!so feel free to download the project file here. I would also give you a real cookie but the technology for sending cookies over the internet hasn't been invented yet, but one day :)
To get it set up just navigate to the directory and follow the steps below.
- Run bundle
- Use rake console to start a pry session and access the model data.
- Try accessing and creating Model data for Appointment, Patient, and Physician. You can do this manually or explore the contents of the seeds.rb file.
- Have fun!