render :json => {
"playlist" => playlist_description,
"songs" => @playlist.songs.as_json(:include => {:playlist_songs => {:only => [:id, :position]}})
}
The above code results in 1+N queries to the database, one to load playlist_songs for each song. The playlist is preloaded in @playlist.
This is so slow, how can I optimize?
My guess: You're not eager-loading the playlist_songs at the moment. You're currently waiting until the as_json call - after which all the songs have been loaded - and then the code has to iterate over every song and fetch the playlist_songs then.
My guess (this is totally untested and may include bugs)
@playlist.songs.all(:include => :playlist_songs).as_json(:include => {:playlist_songs => {:only => [:id, :position]}})
AFAICT, this should first eager load all the songs and the playlist_songs... and then render as json.
I would highly recommend integrating with a JSON builder such as rabl. It will make your life 10x easier moving forward, and is extremely nice to separate the "view" of the JSON representation. I made the switch a couple months ago and haven't looked back.
Within your controller:
@playlist = Playlist.where(:id => params[:id]).includes(:playlist_songs)
Then the rabl template could be something like this:
object @playlist
attribute :description
child :playlist_songs do
attributes :id, :position
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With