Be Gone Superfluous Tables: How Active Record Allows Us to Refer to Different Types of a Model

Robin Kim
3 min readJan 2, 2019

Let’s say we have a User model that has associations with the models Listing and Review, like so:

But as we are building these associations we realize that we want to make it so that a certain type of User — a host — has many listings and a certain type of User — a guest — has many reviews.

-Listing belongs to a specific type of User — a host.
-Review belongs to a specific type of User — a guest.

We can consider creating separate tables for these two types of users but what if we want the User to be able to switch back and forth from being a guest to a host? Fortunately, Active Record offers a solution for this exact situation via the foreign_key and class_name arguments, which we can add in our model definitions.

For this implementation, we start by establishing a Listing belongs_to a host relationship. If we stop here though, Active Record will default to looking for a table named hosts whenever a related query is made, which is problematic because we won’t be creating a separate model or table for Host. The key here then is specifying which table hosts is referring to — in our case, the table users— and we can do that using the class_name argument. We can do the same for the Review model, which has a belongs_to relationship with guest.

<app/models/listing.rb>
<app/models/review.rb>

We also have to include the foreign keys host_id in the listings table and guest_id in the reviews table.

<db/schema.rb>

Additionally, we need to establish two has_many relationships under the User model. We also have to specify which foreign keys Active Record should look for in each respective table. Otherwise Active Record will default to looking for a foreign key called user_id (instead of host_id or guest_id ). This is made possible with the foreign_key argument.

<app/models/user.rb>

Through the associations we’ve created above, a user can now have many listings as a host and many reviews as a guest. Utilizing the class_name and foreign_key arguments saves us from having to create unnecessary tables that may actually end up muddying relationships between models. Cool trick, Active Record!

--

--