Reputation: 2346
I made a partial of a for a song model with artist
, title
, duration
, release
etc.
I want to show all the artists songs on one page, sometimes they have a ton. The query takes 0.08 seconds, but I also see this:
Rendered artist/_song_listing.html.haml (18.2ms)
Rendered artist/_song_listing.html.haml (8.5ms)
Rendered artist/_song_listing.html.haml (7.5ms)
Rendered artist/_song_listing.html.haml (9.6ms)
Rendered artist/_song_listing.html.haml (18.6ms)
Rendered artist/_song_listing.html.haml (12.6ms)
Rendered artist/_song_listing.html.haml (7.8ms)
Rendered artist/_song_listing.html.haml (19.5ms)
(etc etc)
Ultimately this takes 14 seconds, which is way too long.
Is it wrong to use partials in this way? Is there any way to make this faster?
Edit:
ArtistController:
def show
@artist = Artist.find(params[:id])
@songs = @artist.songs.order('published_at DESC').includes(:members)
show.html.haml:
.panel.panel-default
- @artist.songs.each do |song|
=render 'song_listing', song: song
Exerpt from _song_listing
(~500 times):
.row
.col-xs-12
.summary
-if song.summary.present?
="#{song.summary.sanitize.strip.gsub("\u00A0"," ")}"
-else
%i
No Summary
.row
.col-xs-10
%ul.list-inline
- song.members.each do |member|
%li
%span
%img{src:"#{member.image_url}", width: '20px', height: '20px', class: 'img-circle'}
Upvotes: 3
Views: 2069
Reputation: 838
I know it's been ages, but I thought an improvement to the current answers might help others as well
.panel.panel-default
=render partial: 'song_listing', collection: @artist.songs, as: :song
This is much faster in terms of rendering. not as fast as inline rendering, but much better than doing a render for each item.
Upvotes: 2
Reputation: 2621
Is the load coming from the SQL queries? Try pre-loading in your controller.
@songs = Song.all.includes(:artist,:title)
Then something like
@songs.each do |song|
# render logic here for each song
end
In the includes you would put any related associations, which are not loaded automatically.
This should make each partial rendering much faster, if SQL queries were your problem.
Further instructions to include from the first look up:
@artist = Artist.find(params[:id]).includes(:songs => [:members])
@songs = @artist.songs.order('published_at DESC')
I believe this will do the trick for you. However what you had earlier would still be OK. Not sure if the brackets around ":members" are required, but essentially you are saying, include Artist's songs, and for each song include it's members.
Upvotes: 3
Reputation: 319
It sounds like you are possibly doing a database lookup for each song. Try to load all the song data in a single query. It may also help to post your view code if indeed the rendering is the bottleneck.
Upvotes: 1