Testing ActiveRecord associations in the Rails console

Luoana Chirita
Dec 3, 2018 · 5 min read

When building a new Rails app, you usually get to create several models with all kinds of associations between them (see more in the documentation).

The usual steps after creating the app would be as follows:

  1. Create the ActiveRecord models.
  2. Build the ActiveRecord associations within the models (e.g. belongs_to, has_many, has_many: through etc.)
  3. Create the db tables and migrations.
  4. Check the schema to verify that the tables have the correct structure.
  5. Test the ActiveRecord models associations.

This last step is the one we will cover in this tutorial. It is a fairly simple task once you understand the basics, and it can save you a lot of trouble later on when building up on the functionality of your app.

You do need to have some basic knowledge and understanding of arrays, of what a model instance is in OOP, and of some ActiveRecord functions such as .find, .find_by, .first.

For this tutorial, we will work with the following example, in order to cover multiple types of associations (belongs to, has many, has many through):

Building -< Office >- Company -< Employee

This translates in the following associations in each model:

We have created some instances for each model in the seeds file and ran rake db:seed in order to populate my database.

The first step now would be to check that there is data for each model with ModelName.all, which should return an array of the model’s instances every time, eg:

After running .all for each model to see the list of instances, we can start testing the associations.

First, we have Building -< Office (a building has many offices). If all is setup correctly, it means we should be able to run .offices on a building’s instance(let’s choose the first) and have a list (an array) of all offices of that particular building:

Indeed, we get a list of several office instances. So the first association between buildings and offices is correct.

We can now check Office >- Company (a company has many offices, an office belongs to a/has only one company), with .company on a specific office (Office.first), and even access directly one of the company’s attributes, such as .company.name :

We can even go a step further and get the company’s name starting from a building:

Since a building has many offices, as we’ve seen previously, Building.first.offices returns an array of one or more offices. Therefore, to access an office through Building, we have to specify its index in the offices array (in this case we took the first one, by selecting index 0: .[0]).

In plain English, this translates into: for the first building in our list, find the first office in its list of offices and return the name of the company associated with that particular office.

Great! This way we tested the whole part of Building -< Office >- Company relationship.

The only part missing is Company -< Employee. This one is easy: as a company has many employees, we can just call .employees on any instance of a company, which will return a list (array) of employees (instances):

We can now access a specific employee’s attribute by selecting one of the company’s employees by index (remember, we have an array) and calling the attribute’s name:

What if we wanted to access the name of the first employee that works in a particular building, and in a particular office? That sounds really complicated, but it is not! We just put together all the steps we’ve done so far:

  1. Select the building: Building.first, or Building.find(3), etc.
  2. Select the office: .offices[2]
  3. Find the company: .company
  4. Select the employee: .employees[0]

How cool was that?! Want to see something even better?

We can even start the “chain” from the other end (Employee) and go all the way through to Building! This would be useful if we want to find in which building a specific employee works. Let’s look this up for the one we have found in the example above: “Suzanne Jonathan Hansen”. The steps are quite similar, just reversed:

  1. Select the employee: Employee.find_by(name: “Suzanne Jonathan Hansen”)
  2. Find the company: .company
  3. Select the office: .offices[0]
  4. Find the building: .building

Conclusion:

Being able to test your models associations in the console not only helps you check that they have been correctly built, it also gives you an invaluable understanding of your models and of how to access each of their properties to find the data you want. You can further use these concepts to test new functions in the console and make sure their result is correct, such as:

In this example, we can see that the rent_per_floor of the Building.first is 18000, and that we have an array of 3 instances of offices for this building (Building.first.offices), which means that the result of Building.first.total_rent is correct (18000 * 3 = 54000).

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade