Reputation: 1895
I have a model Playlist, and a model User, both of which have_many of each other, through a join model PlaylistUser.
On my playlists#show action, I want to print a list of all of a Playlist's Users, along with the first two Playlists (ordered by :song_count) associated with each of those Users. To make this only one query, I eager loaded the Playlist table along with the Users.
Right now here's what I have:
playlists/show.html.erb
<% @playlist = Playlist.find(params[:id]) %>
<% @playlist_users = @playlist.users.includes(:playlists)
<% @playlist_users.each do |user| %>
<%= user.name %>
<%= user.playlists.order(:song_count).reverse.first.name %>
<%= user.playlists.order(:song_count).reverse.second.name %>
<% end %>
models
class User < ActiveRecord::Base
has_many :playlist_users
has_many :playlists, :through => :playlist_users
end
class PlaylistUser < ActiveRecord::Base
belongs_to :playlist
belongs_to :user
end
class Playlist < ActiveRecord::Base
has_many :playlist_users
has_many :users, :through => :playlist_users
end
When I remove the ordering, the query is extremely fast. But with the ordering, it's very slow, because the database apparently has to query each Playlist before it can order them.
Can I order the Playlists in the original query?
Upvotes: 1
Views: 43
Reputation: 115541
actually when you do:
user.playlists.order(:song_count).reverse
You dont leverage the eagerload, you redo queries each time.
Thanks to eagerloading you have the collection in memory, so you can sort it using ruby method like sort:
user.playlists.sort_by {|pl| -pl.song_count }
Upvotes: 2