Get all related data for all model type records in Rails?

How to combine together all related data for all records in a given model?

I have the following models:

User --N:1--> Reservation <--1:N-- Concert

      

So the pseudocode:

Reservation belongs_to User
Reservation belongs_to Concert
User has_many Reservations
User has_many Concerts through Reservations
Concert has_many Reservations
Concert has_many Users through Reservations

      

How do I make one big array of everything?

  • I can receive all my orders through Reservation.all

  • I can get a User for a specific reservation via Reservation.find(25).user

  • I can get a Concert for a specific reservation via Reservation.find(25).concert

But how do I get it for everyone? If i do

Reservation.all.each do |res|
   res.user.name+","+res.concert.name+","+res.concert.date # etc.
end

      

It will then execute two new database queries for each reservation as it scrolls through it. It may not matter for 10 entries, but for thousands it can be very painful. Add other associations to it (e.g. Concert belongs to_place, user has an email address, etc.) ...

Is there a way to say "Get all caveats and next attached information" so that it gets loaded into one SQL query?

+3


source to share


1 answer


What you are trying to accomplish is called eager loading and can be accomplished with includes

c ActiveRecord

. See below:

Problem N + 1 queries

Active entry allows you to pre-specify all associations to be loaded. This is possible by specifying a method to include the call to Model.find. With Active Record enabled, ensures that all specified associations are loaded using as few queries as possible.

http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

In your example, you can use the following:

Reservation.all.includes(:user, :concert)

      


It is also helpful to specify a parameter :inverse_of

for your relationship :belongs_to

. This optimizes the loading of the object and ensures that the model cross-reference returns to the same object in memory, i.e .:



@user == @user.reservations.first.user # true

      

More information is available here:

If you are using the role_to property in a connection model, it is recommended that you set the: inverse_of option on the belongs_to property ...

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

In your example:

# app/models/reservation.rb

belongs_to :user, :inverse_of => :reservations
belongs_to :concert, :inverse_of => :reservations

      

+2


source







All Articles