简体   繁体   中英

Rails: N+1 queries being generated

I have a Conversation model that has_many messages. In my query, I have

@active_conversations = Conversation.includes(:messages)..........

This solved my N+1 queries for the most part. Here is my problem:

index.html.erb

<% @active_conversations.each do |conversation| %>

<div class="<%= 'unread' if conversation.has_unread_messages?(current_user) %>">

<span><%= conversation.messages.first.body.truncate(50) %></span>

</div> 

<%end%>

Conversation.rb

  def has_unread_messages?(user)
    !self.messages.unread.where(:receiver_id => user.id).empty?
  end

Message.rb

  def self.unread
    where("read_at IS NULL")
  end

There is no n+1 issue for conversation.message.body

The issue is with - if conversation.has_unread_messages?(current_user) because for every conversation it is running that query to check if the messages in that conversation have not been read.

As you have included the :messages on your query, you have all messages loaded, so you don't really need another query to check if it is unread and if all the conversation messages are unread. You can create methods that check these states:

def has_unread_messages?(user)
  unread = self.messages.collect {|m| m.read_at.nil? && m.receiver_id == user.id}
  !unread.empty?
end

All of your messages inside the @conversation.messages are preloaded.

Updated

Here is updated solution:

def has_unread_messages?(user) 
  messages.any? { |message| message.read_at.nil? && message.receiver_id == user.id } 
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM