Для этого вам нужно иметь область с GROUP BY
, чтобы получить последний комментарий по каждой теме.Затем вы можете заказать эту область по created_at
, чтобы получить самые последние комментарии к темам.
Следующее работает для меня, используя sqlite
class Comment < ActiveRecord::Base
belongs_to :topic
scope :recent, order("comments.created_at DESC")
scope :latest_by_topic, group("comments.topic_id").order("comments.created_at DESC")
end
class Topic < ActiveRecord::Base
has_many :comments
scope :hot, joins(:comments) & Comment.latest_by_topic & limit(5)
end
Я использовал следующий seed.rb для генерацииданные теста
(1..10).each do |t|
topic = Topic.new
(1..10).each do |c|
topic.comments.build(:subject => "Comment #{c} for topic #{t}")
end
topic.save
end
И вот результаты теста
ruby-1.9.2-p0 > Topic.hot.map(&:id)
=> [10, 9, 8, 7, 6]
ruby-1.9.2-p0 > Topic.first.comments.create(:subject => 'Topic 1 - New comment')
=> #<Comment id: 101, subject: "Topic 1 - New comment", topic_id: 1, content: nil, created_at: "2010-08-26 10:53:34", updated_at: "2010-08-26 10:53:34">
ruby-1.9.2-p0 > Topic.hot.map(&:id)
=> [1, 10, 9, 8, 7]
ruby-1.9.2-p0 >
SQL, сгенерированный для sqlite (переформатированный), чрезвычайно прост, и я надеюсь, что Arel будет представлять другой SQL для других движковпоскольку это, безусловно, приведет к сбою во многих механизмах БД, поскольку столбцы в разделе «Тема» не находятся в «Группе по списку».Если это действительно представляет проблему, то вы, вероятно, можете ее преодолеть, ограничив выбранные столбцы только комментариями .topic_id
puts Topic.hot.to_sql
SELECT "topics".*
FROM "topics"
INNER JOIN "comments" ON "comments"."topic_id" = "topics"."id"
GROUP BY comments.topic_id
ORDER BY comments.created_at DESC LIMIT 5