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