Eager loading backreferences in ActiveRecord in Rails -
apparently in rails application activerecord running more sql queries like. have simple one-to-many relation. each package…
class package < activerecord::base has_many :screenshots end
…there several screenshots…
class screenshot < activerecord::base belongs_to :package def image_url "/screenshots/#{self.package.name}/#{self.id}_#{size}.png" end end
my first simple task show index page packages , screenshots. each package want show screenshots. path screenshot image determined package name. let's example , fetch package record "3dchess" package:
pkg = package.includes(:screenshots).find_by_name('3dchess')
as can see eager-load screenshots. activerecord runs these 2 sql queries:
package load (1.4ms) select "packages".* "packages" "packages"."name" = '3dchess' limit 1 screenshot load (2.1ms) select "screenshots".* "screenshots" "screenshots"."package_id" in (243)
i had expected done in 1 query don't mind two. when i'm displaying 20 screenshots on index page 20 additional sql queries. , turns out caused virtual attribute "image_url" of screenshot model.
what i'm doing in template:
<% @packages.each |package| %> <li> <% if package.screenshots %> <%= image_tag package.screenshots.first.image_url %> <% end %> </li> <% end %>
and each call of "image_tag package.screenshots.first.image_url" runs sql query like:
select "packages".* "packages" "packages"."id" = $1 order "packages"."id" asc limit 1
so although i'm eagerloading screenshots when i'm loading package - not work other way round.
or put way - creates 2 sql queries mentioned above:
pkg = package.includes(:screenshots).find_by_name('3dchess')
but when try access
pkg.package
then activerecord runs additional query getting "package" information although should have them.
so question is: how can make activerecord eager-load backreference "screenshot" "package" automatically?
Comments
Post a Comment