A Dive Into Active Record Associations

What you need to know about: migrations, models and more as a new developer

Nowadays it’s hard to imagine websites or web applications without having a database. Ruby has such a wonderful tool called Active Record. Active record is the interface that gives you to link the database to your application, it lets you structure your data modules in a logical and nearly plain English way. Active Record is like a bridge between Ruby and Database. First and foremost, in Rails an association is a connection between two (or more) active records models. Let’s dive into it:

Why do we need Associations between models?

They make common operations simpler and easier without having to write tons of code.

Without associations, the model declarations would look like this:

Want to read this story later? Save it in Journal.

Now if we want to add a new wish for an existing destination, we would need to do something like this.

@wish = Wish.create(wish_note: “Climb the Giza Pyramid”, destination_id: @destination.id)

Today I will focus particularly on associations and how to implement them.

It all starts in the database. You need to create your tables and the relationship between them to visualize how the tables are connected to each other and decide where you want to place the foreign keys.

For every relationship, there is a foreign key somewhere. Foreign Keys are columns that refer to the primary key of another table. Conventionally, foreign keys in active records are comprised of the name of the model you are referencing. In our example foreign key for the table “wishes” is destination_id and for the table “bucket_list_items” is traveler_id, wish_id.

The following step would be to write down our migrations accordingly after we know the names of our tables, columns and the location of foreign keys.

In Rails you can generate migrations by running the following command rails g migration name_of_the_table_plural name_of_the_column:datatype (There are a few other handy rails commands which is another subject for a blog).

For example, the command to generate the table destinations would look like this:

rails g migration Destinations destination_name:string

Now we can go ahead and run this command rails db:migrate in your terminal to execute our table creations.

For our tables the generated Schema looks like this:

By using Active Record’s macro-style association class methods, we can add some convenient instance methods to our models.

Now we can implement all of the associations we’ve been discussing.

We will be using the following AR Macros (or methods):

- belongs_to

- has_many

- has_many :through

The most common relationship is , and it is declared in Active Record with belongs_to and has_many.

belongs_to

Foreign keys correspond to the belongs to Marco on the model. One-to-one and many-to-one relationships only require a single foreign key, which is stored in the “owned” model.

Each BucketListItem is associated with Traveler and Wish.

Now we have access to some new instance methods , like traveler and wish.

@bucket_list_item.traveler_id = 7
@bucket_list_item.traveler

This will return the actual Traveler object that is attached to that @bucket_list_item.

has_many and has_many through

Many-to-many relationships require a join table containing a foreign key for both models. The models are joined using has_many :through statements. Now, because our wishes table has a destination_id column and because our Destination class uses the has_many macro, a destination has many wishes. It is also true that destination has many bucket_list_items through wishes. We are using the has_many through macro to implement this:

Since our wishes table has destination_id we use belongs_to macro, our wish class has many bucket_list_items. It is also true that a wish has_many travelers through bucket_list_items. We will use the has_many through macro to implement this.

Similarly for the following model Traveler.

And that’s it!

Order and direction of operations does matter when establishing associations between models, it is typically better to update has_many side of a relationship to get the full benefit of Active Record’s power. Still, as we can see, with just migrations and Active Record macros, we can start to build and persist associations between models.

Displaying data via belongs_to, has_many and has_many :through relationship looks identical to displaying data through a normal relationship. That's the beauty of abstraction –– all of the details about how our models are associated with each other get abstracted away, and we can focus simply on the presentation. As a new developer these are your fundamentals. It will get better with time and this article can be your guide.

📝 Save this story in Journal.

👩‍💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.