Я полагал, что единственным хорошим решением является использование второй модели для хранения самых последних сообщений для каждого потока (из-за проблем с производительностью при использовании GROUP BY с вложенным выбором, см. Мои комментарии). Это не займет много места в БД, потому что мы храним только идентификаторы, а не текст или даже BLOB-объекты.
Модель RecentMessages будет выглядеть примерно так:
create_table :recent_messages do |t|
t.integer :sender_id
t.integer :recipient_id
t.integer :message_id
t.integer :message_thread_id
t.timestamps
end
class RecentMessage < ActiveRecord::Base
belongs_to :message
belongs_to :message_thread, :class_name => 'Message'
belongs_to :sender, :class_name => 'User', :foreign_key => "sender_id"
belongs_to :recipient, :class_name => 'User', :foreign_key => "recipient_id"
end
Основная идея: все сообщения хранятся в одной модели (сообщения). Каждый раз, когда новое сообщение добавляется в поток (или создается поток), происходят две вещи (например, с обратным вызовом after_save):
- Сохранить новое сообщение в модели RecentMessages (что означает sender_id, receient_id, message_id, message_thread_id (= parent_id || id))
- Получить самое последнее сообщение (из этой цепочки в сообщениях), где sender_id == receient_id и наоборот (примечание: это работает только в том случае, если модель сообщений должна поддерживать сообщения только между двумя пользователями), и сохранить его в модели RecentMessages как хорошо (если найден и если его там еще нет)
Конечно, должно быть только макс. 2 последних сообщения хранятся в БД для каждого сообщения в любой момент времени.
Если кто-то хочет показать входящие, должно произойти следующее:
@messages = current_user.recent_received_messages.paginate :page => params[:page], :per_page => 10, :order => "created_at DESC", :include => :message
Это лучшее, что я понял до сих пор. Я все еще думаю, что это некрасиво, но это быстро, и это работает. Если кто-нибудь придумает лучшее решение, я буду благодарен!