Method to count unread messages
About your code:


As a general rule, the imperative pattern acc = 0; xs.each { |x| acc += f(x) }; total = acc should be replaced by the functional expression total = xs.reduce(0) { |acc, x| acc + f(x) } or total = xs.map { |x| f(x) }.reduce(0, :+). Given that Rails provides an Enumerable#sum, it can be simplified even more: total = xs.map { |x| f(x) }.sum.
That said, this is not the way you do things in Rails, you should use associations and scopes. The code will be much faster (all the processing is performed by the database engine) and more reusable.


I'd write:

class User 
  has_many :conversations, -&gt;(user) { Conversation.with_user(user) }
  has_many :messages, through: :conversations

  def unread_messages_count
    messages.not_sent_by(self).unread.count
  end
end

class Conversation
  scope :with_user, -&gt;(user) { where("? IN (user1_id, user2_id)", user.id) }
end

class Message
  scope :unread, -&gt; { where(read: false) }
  scope :not_sent_by, -&gt;(user) { where.not(user: user) }
end


Note that we could write the where-condition of with_user directly in the has_many block, but this way we respect encapsulation: the User model knows nothing about the attributes of the Conversation table.