Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord - nested includes

I'm trying to perform the following query in Rails 5 in a way that it doesn't trigger N+1 queries when I access each events.contact:

events = @company.recipients_events
                 .where(contacts: { user_id: user_id })

I tried some combinations of .includes, .references and .eager_loading, but none of them worked. Some of them returned an SQL error, and other ones returned a nil object when I access events.contact.

Here's a brief version of my associations:

class Company
   has_many :recipients
   has_many :recipients_events, through: :recipients, source: :events
end

class Recipient
   belongs_to :contact
   has_many :events, as: :eventable
end

class Event
   belongs_to :eventable, polymorphic: true
end

class Contact
   has_many :recipients
end

What would be the correct way to achieve what I need?

like image 928
felipeecst Avatar asked Jan 29 '26 17:01

felipeecst


1 Answers

If you already know user_id when you load @company, I'd do something like this:

@company = Company.where(whatever)
  .includes(recipients: [:recipients_events, :contact])
  .where(contacts: { user_id: user_id })
  .take
events = @company.recipients_events

OR, if not:

events = Company.where(whatever)
  .includes(recipients: [:recipients_events, :contact])
  .where(contacts: { user_id: user_id })
  .take
  .recipients_events

The ActiveRecord query planner will determine what it thinks is the best way to get that data. It might be 1 query per table without the where, but when you chain includes().where() you will probably get 2 queries both with left outer joins on them.

like image 98
Jacob Vanus Avatar answered Jan 31 '26 08:01

Jacob Vanus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!