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?
source to share
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
source to share