简体   繁体   中英

Eager load Paperclip's has_attached_file data?

Product has_many:assets

Asset belongs_to:product

Asset has_attached_file:photo using Paperclip (with all your standard Paperclip options; a few styles, S3 storage).

If I form a Product query like p = Product.includes(:assets) I can call each of the actual attributes of Asset without incurring any additional database queries, like:

p = Product.includes(:assets)
p.each { |a| print a.assets.first.title }

The title attribute on Asset (which is a database column) prints, no queries made.

To get the URL generated by Paperclip:

p = Product.includes(:assets)
p.each { |a| print a.assets.first.photo.url }

causes a separate additional query for each Product :

Product Load (0.3ms)  SELECT "products".* FROM "products" WHERE "products"."id" = 2 LIMIT 1

According to this G.Groups posting , I shouldn't be hitting the database with each pass through the loop, but I am.

Is there a way to not incur the additional database hit for each iteration, but gather all the data all at once? Am I overlooking something simple?

Rails 3.0.9, REE 1.8.7, Paperclip 2.3.11.

updated, fixed

The issue is that in my Paperclip settings, I have :product_id as part of the :path : :attachment/:product_id/:filename-:style.:extension , which is causing the additional Product query for each iteration through the loop.

By changing the query to p = Product.includes(:assets => [:product]).all , it removed the additional query.

I think you're overlooking something simple:

p = Product.includes(:assets).all

includes sets the relation to eager load the association, all does the actual query.

irb(main):001:0> p = Product.includes(:assets)
=> ..........
irb(main):002:0> p.class
=> ActiveRecord::Relation
irb(main):003:0> p.all.class
=> Array

We can get to the root of the problem much faster if you use one of the query analyzer plugins Try query-reviewer, or if you're using newrelic, the dev mode includes this. You'll get a stack trace for every query. I don't think it has anything to do with eager loading - if it did, you'd be getting extra Asset loads instead of Product loads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM