I am not very familiar with RoR but my colleague has written this code for one of our applications & I have a feeling this is just too un optimized and too many queries for a simple task.
We have 3 tables. Artist, Album & Song. Artist can have multiple albums. Album can have multiple songs. We are trying to output the top 10 songs based on a field popularity_total in the songs table. Then there are other tables that capture likes etc.
def top
# a list of 10 most played songs in the past week
@toplistsongs = Song.select(INDEX_COLUMNS).order("popularity_total,created_at DESC").limit(10)
@toplistsongs.each do |song|
song['urls'] = song.get_song_urls
song['artist'] = song.get_song_artist
song['genre'] = song.tag_list
song['hearts'] = song.likers(User).count
song['like_status'] = ( current_user!=nil ? current_user.likes?(song) : false )
song['impressions'] = song.impressionist_count
song['albums'] = song.get_song_album
end
@w = {'top' =>
{
'song' => @toplistsongs
}
}
respond_with(@w)
end
Every fetch inside the loop with result in a hit on the db. I have a feeling there are too many queries happening in the loop for each song when ideally they can all be done using single query for all the songs. Can anyone suggest if this is a standard rails way of handling things or is this outright bad code?
Thanks for all the help.
You can use ActiveRecord includes method in order to reduce DB queries count. For example:
This will produce 5 queries for the whole top method and is not dependent on the number of songs you want to present. In other words the number of queries is constant.
You will have to use ActiveRecord associations for this to work. I can see that you are using the method
get_song_artistI assume it is not made by an association.To form your relationship in ActiveRecord associations you will have to use the has_many, has_one and belongs_to operators.