我正在尝试通过最近的评论设置主题索引的顺序。这是有效的:
Topic.joins(:comments).order("comments.created_at desc")
但它不止一次列出了主题。
有没有办法将每个主题的显示次数限制为一个?
我正在尝试通过最近的评论设置主题索引的顺序。这是有效的:
Topic.joins(:comments).order("comments.created_at desc")
但它不止一次列出了主题。
有没有办法将每个主题的显示次数限制为一个?
好的,发生的事情是这样的:当您加入评论时,您会为每个评论获得一个数据库行,这(如果主题上有多个评论)意味着每个主题记录的多个副本。
要解决此问题,您需要使用分组,以便每个主题只有一个结果。分组依据是您返回的模型的 id ( topics.id
)。现在,还有更多内容 - 因为每个结果仍然有多个评论,每个结果也有多个 created_at 值,因此(为了按它排序,就像你做的那样)你需要告诉数据库使用哪一个。
这是通过某种聚合函数完成的。我猜你希望最近的评论是决定顺序的评论。如果这是真的,代码将是这样的:
Topic.joins(:comments).select('topics.*, max(comments.created_at) as last_comment').group('topics.id').order('last_comment desc')
自定义选择包括您需要的常用数据(关于主题对象的所有信息 - topics.*
)以及在评论创建日期使用的聚合函数(max()
,顾名思义,它返回最大的可能值。)。较近的日期较大,因此这将是最近评论的创建日期戳。该结果别名为last_comment
(using ),因此您可以在调用as
中引用它。.order
我发现解决问题的最优雅的方法是touch
在评论模型中添加多态关联:
belongs_to :commentable, :polymorphic => true, touch: true
如果您不使用多态关联,则可以使用:
belongs_to :topic, touch: true
然后,我所要做的就是将主题模型中的默认范围更改为updated_at
default_scope order: 'topics.updated_at DESC'
添加touch
到评论意味着每次向主题添加评论时,它都会更新主题中的 updated_at 列。
在我使用的控制器中:
@topics = Topic.order(sort_column + " " + sort_direction).paginate(:per_page => 20, :page => params[:page])
Topic.all
或者其他东西也可以在那里工作。
感谢我的超级朋友 Alain 向我指出了这一点。