DEV Community

Cover image for ActiveRecord Associations intro into 'has_many'
AaronDski
AaronDski

Posted on

ActiveRecord Associations intro into 'has_many'

When learning about ActiveRecord in our coding bootcamp, they talked about the major benefits that ActiveRecord provides when working in Ruby and SQL. So I wanted to delve more into what is happening behind the scenes, and I discovered there is a lot that ActiveRecord is doing back there. So let's talk about one that we all use: has_many.

Has_many is one of the 6 types of associations (or "macro methods") that ActiveRecord offers.
A has_many association is similar to has_one, but indicates a one-to-many connection with another model. You'll often find this association on the "other side" of a belongs_to association. This association indicates that each instance of the model has zero or more instances of another model. With the has_many association you will always want to make sure that whatever the model has_many of, is plural. For example, in an application containing a child and their toys, the child model could be declared like this:

class Child < ApplicationRecord
  has_many :toys
end
Enter fullscreen mode Exit fullscreen mode

A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model. Also with the has_many :through association, you will still want to make sure that whatever the model has_many of is plural. For example, consider a game has reviews and users that can write reviews. The relevant many-to-many association declarations could look like this:

class Game < ApplicationRecord
  has_many :reviews
  has_many :users, through: :reviews
end

class Review < ApplicationRecord
  belongs_to :game
  belongs_to :user
end

class User < ApplicationRecord
  has_many :reviews
  has_many :games, through: :reviews
end
Enter fullscreen mode Exit fullscreen mode

Okay, now that we have that basic setup of what the has_many table association can look like, lets get into what is auto-generated for you. Look at the list below:

others                            
others=(other,other,...)          
other_ids                         
other_ids=(id,id,...)             
others<<                          
others.push                       
others.concat                     
others.build(attributes={})       
others.create(attributes={})      
others.create!(attributes={})     
others.size                       
others.length                     
others.count                      
others.sum(*args)                 
others.empty?                     
others.clear                      
others.delete(other,other,...)    
others.delete_all                 
others.destroy(other,other,...)   
others.destroy_all                
others.find(*args)                
others.exists?                    
others.distinct                   
others.reset                      
others.reload     
Enter fullscreen mode Exit fullscreen mode

These auto-generated methods can and will save us a ton of time when querying any database.

Here is another cool thing that has_many can do: since associations are built from Relation objects, you can add conditions to the query, like so:

class Blog < ActiveRecord::Base
  has_many :published_posts, -> { where(published: true) }, class_name: 'Post'
end
Enter fullscreen mode Exit fullscreen mode

You can also read up on more of the capabilities that 'Association Methods' have, Here.

Furthermore, if you would like to learn more about the other five associations, here is a link with detailed documentation on those association types and their use cases ActiveRecord.

In conclusion, has_many is a very helpful method that saves us a lot of time. I personally have made many methods not knowing that has_many already provided said method. So it's a good thing to to be curious about whats happening or what the method is doing for you. post in the comments below about a time when a 'Macro' method saved you time.

Discussion (0)