maksfromspb
maksfromspb

Reputation: 177

Rails has_many :through and N+1

I have two associated models: Chat and User through Memberships model

class Chat < ActiveRecord::Base
 has_many :memberships
 has_many :members, through: :memberships
end

class Membership < ActiveRecord::Base
 belongs_to :chat
 belongs_to :member, class_name: "User", foreign_key: 'user_id'
end

In the controller I retrieve records like that:

@chats = Chat.joins(:memberships).includes([:owner, :memberships=>:member])
.where("chats.owner_id = ? OR memberships.user_id = ?", current_user.id, current_user.id)

And in view I display chats with JBuilder like that:

json.extract! @chat, :id
   json.members @chat.memberships.order('id ASC') do |membership|
     json.name membership.member.name
   end
end

But Rails generate a lot of db queries and the view rendering takes a long time:

Completed 200 OK in 1597ms (Views: 1393.8ms | ActiveRecord: 150.8ms)

How can I optimize and speed up these queries?

Upvotes: 4

Views: 1674

Answers (1)

evanbikes
evanbikes

Reputation: 4171

I think the problem here is this:

You are including :memberships, in the joins, so if you call chat.memberships it will use the memberships stored in memory.

But you are calling chat.memberships.order('id ASC') which is a sql query that Rails hasn't cached and so will have to call.

The simple solution is to sort in Ruby and not SQL:

chat.memberships.sort_by(&:id)

Upvotes: 6

Related Questions