I have 4 models, let's say:
class Photo < ActiveRecord::Base
belongs_to :photoable, polymorphic: true
end
class User < ActiveRecord::Base
has_one :photo, as: :photoable
end
class Company < ActiveRecord::Base
has_one :photo, as: :photoable
has_many :products
end
class Products < ActiveRecord::Base
belongs_to :company
end
So, the query Photo.all.includes(:photoable)
works.
But if I use Photo.all.includes(photoable: :products)
only works if all loaded photos belongs to Company. If the relation contains photos of users and companies, this error is raised:
ActiveRecord::ConfigurationError (Association named 'products' was not found; perhaps you misspelled it?):
This occurs because user hasn't relationship with products.
Is there any way to eager load users and companies with products for a relation of photos?
EDIT:
This question isn't duplicated of Eager load polymorphic. As I commented below, in this question I want to do eager load for polymorphic associations which has different associations(one has products and the other don't). In that question, the OP uses wrong names for table names.
You can avoid most n+1 queries in rails by simply eager loading associations. Eager loading allows you to load all of your associations (parent and children) once instead of n+1 times (which often happens with lazy loading, rails' default). As seen above, . includes allows nested association eager loading!
The n+1 query problem is one of the most common scalability bottlenecks. It involves fetching a list of resources from a database that includes other associated resources within them. This means that we might have to query for the associated resources separately.
In Ruby on Rails, a polymorphic association is an Active Record association that can connect a model to multiple other models. For example, we can use a single association to connect the Review model with the Event and Restaurant models, allowing us to connect a review with either an event or a restaurant.
Eager loading lets you preload the associated data (authors) for all the posts from the database, improves the overall performance by reducing the number of queries, and provides you with the data that you want to display in your views, but the only catch here is which one to use. Gotcha!
You may add specific associations to Photo
model:
class Photo < ActiveRecord::Base
belongs_to :photoable, polymorphic: true
belongs_to :user, -> { where(photoable_type: 'User' ) }, foreign_key: :photoable_id
belongs_to :company, -> { where(photoable_type: 'Company' ) }, foreign_key: :photoable_id
end
After that you may preload nested specific associations:
photos = Photo.all.includes(:photoable, company: :products)
With access to records like this:
photos.each do |photo|
puts photo.photoable.inspect
puts photo.company.products.inspect if photo.photoable_type == "Company"
end
This approach loads company
association twice, but does not do n+1 queries.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With