Jer*_*iko 11 activerecord ruby-on-rails arel
我用新scope方法(Arel 0.4.0,Rails 3.0.0.rc)轻微阻止了
基本上我有:
一个topics模型,它has_many :comments和一个comments模型(带有一topic_id列)belongs_to :topics.
我正在尝试获取"热门话题"的集合,即最近评论过的主题.目前的代码如下:
# models/comment.rb
scope :recent, order("comments.created_at DESC")
# models/topic.rb
scope :hot, joins(:comments) & Comment.recent & limit(5)
Run Code Online (Sandbox Code Playgroud)
如果我执行Topic.hot.to_sql,则触发以下查询:
SELECT "topics".* FROM "topics" INNER JOIN "comments"
ON "comments"."topic_id" = "topics"."id"
ORDER BY comments.created_at DESC LIMIT 5
Run Code Online (Sandbox Code Playgroud)
这样可以正常工作,但它可能会返回重复的主题 - 如果主题#3最近被多次评论过,则会多次返回.
我的问题
我将如何回归一组独特的主题,记住我仍然需要访问该comments.created_at领域,以显示最后一篇文章的持续时间?我会想象一下distinct或者是什么group_by,但我不太清楚如何最好地去做.
非常感谢任何建议/建议 - 我已经添加了100个代表奖金,希望很快能找到一个优雅的解决方案.
解决方案1
这不使用Arel,而是使用Rails 2.x语法:
Topic.all(:select => "topics.*, C.id AS last_comment_id,
C.created_at AS last_comment_at",
:joins => "JOINS (
SELECT DISTINCT A.id, A.topic_id, B.created_at
FROM messages A,
(
SELECT topic_id, max(created_at) AS created_at
FROM comments
GROUP BY topic_id
ORDER BY created_at
LIMIT 5
) B
WHERE A.user_id = B.user_id AND
A.created_at = B.created_at
) AS C ON topics.id = C.topic_id
"
).each do |topic|
p "topic id: #{topic.id}"
p "last comment id: #{topic.last_comment_id}"
p "last comment at: #{topic.last_comment_at}"
end
Run Code Online (Sandbox Code Playgroud)
确保索引表中的created_at和topic_id列comments.
解决方案2
last_comment_id在Topic模型中添加一列.last_comment_id创建评论后更新.此方法比使用复杂SQL确定最后一条注释要快得多.
例如:
class Topic < ActiveRecord::Base
has_many :comments
belongs_to :last_comment, :class_name => "Comment"
scope :hot, joins(:last_comment).order("comments.created_at DESC").limit(5)
end
class Comment
belongs_to :topic
after_create :update_topic
def update_topic
topic.last_comment = self
topic.save
# OR better still
# topic.update_attribute(:last_comment_id, id)
end
end
Run Code Online (Sandbox Code Playgroud)
这比运行复杂的SQL查询以确定热门主题更有效.
| 归档时间: |
|
| 查看次数: |
10547 次 |
| 最近记录: |