Rails - Why does LINK_To Generate an unnecessary hit to the database?
I have the following code:
<% @photos = Photo.wh开发者_高级运维ere(:photo_album_id => storyitem.feeded_id).limit(4) %>
<%= link_to 'Image Set', project_photo_album_path(storyitem.project, @photos.first.photo_album_id) %>
In my logs, I see:
Photo Load (0.4ms) SELECT "photos".* FROM "photos" WHERE ("photos"."photo_album_id" = 72) ORDER BY photos.created_at DESC, photos.version DESC LIMIT 1
Photo Load (0.7ms) SELECT "photos".* FROM "photos" WHERE ("photos"."photo_album_id" = 72) ORDER BY photos.created_at DESC, photos.version DESC LIMIT 4
After debugging, it's the link_to that is generating that extra database hit even though the first hit for 4 records finds the first query i need for the link_to.
Is there a way to prevent this query from hitting the db 2 times. I want just the query that gets a limit 4, which should give the app all the info it needs.
Thoughts?
UPDATE:
I'd also like to be able to output the following:
<%= @photos.first.photo_album.title %>
but that too hits the database again. Any way to hit the database only once for all of the above? thxs
I believe the first hit occurs in code before what you are showing.
Are you sure the line
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>
hits the database? Because of lazy loading I think it's only when the second line is run that the database is hit.
I think you need to do more debugging to see where the first database hit occurs.
As for your update, change the first line to
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).includes(:photo_albums) %>
to load the photo albums in the same query.
In your case,
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>
returns a ActiveRecord::Relation
object and it will not hit the DB until you call an enumerable
method on it. Or alternatively you call first
, all
or last
on it. Which is done in your second line,
<%= link_to 'Image Set', project_photo_album_path(storyitem.project, @photos.first.photo_album_id) %>
Where else in the code are you using @photos
?
If you want to absolutely avoid a second call, just call the all
method on @photos
. Like this:
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).all %>
Then for all subsequent uses, it will not hit the DB again. If you further want to avoid a DB hit for photo_album
, then you can use include
:
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).include(:photo_albums).all %>
精彩评论