Properly Associating Many to Man

During development, you may find you need to associate two models through a many-to-many relationship, whereby each instance of a model can be matched with any number of instances of the other model, and vice versa.

There are essentially two methods by which to create such an association, so we’ll briefly discuss both options and why one method in particular (has_many :through) is the far superior implementation.

  • The has_and_belongs_to_many Association
Ruby on Railes many to many
Properly Associated ruby on Railes
Ruby on Rales column

For a truly basic many-to-many relationship of two models, you can declare a has_and_belongs_to_many association in both models, like so:

This would then require you to create a simple database table to represent that relationship.  Your migration file would look something like this:

Now, in addition to the separate authors and books tables, you also have the authors_books table that simply has two columns to associate the id field of one author and one book.  An instance of a model can then reference the other through this association:

  • Why the has_many: through Association Wins

While has_and_belongs_to_many is sufficient for the most rudimentary many-to-many relationship, it’s a very weak and limited solution, particularly for future-proofing.

The biggest limitation with the has_and_belongs_to_many association is that the associative model it creates — authors_books in our example above — has no room for expansion in the future.  Later in development, imagine we need a model field that indicates which chapter(s) of a book a particular author worked on.

With has_and_belongs_to_many, there’s no simple way to track that information, because neither the books nor authors database table would allow for storage of all the necessary information (the book plus the author plus the chapters).  Suddenly, the has_and_belongs_to_many association we’re using needs to be scrapped or a huge workaround needs to be figured out so we don’t screw up live data.

Enter the far superior solution of the has_many :through association.  This model configuration utilizes not only a third database table but most importantly, also utilizes a third model through which the two base models can be associated with one another.  With access to the third “connector” model, we now have the freedom to add attribute fields or any other logic we might need in the future.

Ruby on rails association example

To use the has_many :through association for our example, we’d do something like this:

With the authorship model in place for our many-to-many relationship between books and authors, we can now easily modify the authorship model in the future, adding a column for :edited_chapters or anything else we might need.

In short, while it requires a bit more time and effort to initially setup, you should always use the has_many :through association anytime a many-to-many relationship is required.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *