Ruby on Rails 4.2.0で実装を行なっています。
以下のようなデータ構造をもつMessageモデルがあるとします。

# == Schema Information
#
# Table name: messages
#
#  id           :integer          not null, primary key
#  from_user_id :integer          not null
#  to_user_id   :integer          not null
#  content      :text             not null
#  created_at   :datetime         not null
#  updated_at   :datetime         not null

ここで、ユーザごとにやりとりしたメッセージの新着1件ずつを取得したいと考えています。

例えば、指定したユーザがやりとりしたメッセージの一覧は以下のようなscopeで定義できると思います。

scope :related_to, ->(user) { where('from_user_id = :user_id OR to_user_id = :user_id', user_id: user.id) }

これだとユーザごとにすべてのメッセージが取得されてしまいます。

実現したいことは、イメージとしては「from_user_idto_user_idのどちらかについて、1ユーザあたり1件しか取得できない」という条件になると思っています。

汚い書き方をするなら、こうなると思います:

  1. related_to(user)from_user_idto_user_idをマージする(配列化)
  2. 配列から自分のIDを取り除く
  3. uniqで重複を取り除く(ここで最新メッセージをやりとりしたユーザIDが取得できる)
  4. 3のそれぞれ最新のメッセージを取得する

よい書き方があれば教えていただければと思います。
よろしくお願いします。


追記です。
ざっくりと、以下のようなコードになるかと思います。
よい書き方があれば、ぜひ回答ください。

module Messages
  class HeadlinesFinder
    def initialize(user)
      @user = user
      @messages = []
      @other_user_ids = []
    end

    def call
      messages = Message.order(created_at: :desc).related_to(@user)

      messages.each do |message|
        other_user_id = (message.from_user_id == @user.id) ? message.to_user_id : message.from_user_id

        unless other_user_id.in?(@other_user_ids)
          @messages << message
          @other_user_ids << other_user_id
        end
      end

      @messages
    end
  end
end

使い方:

@headlines = Messages::HeadlinesFinder.new(current_user).call