gpt4 book ai didi

ruby-on-rails - 按带分页的关联模型排序

转载 作者:行者123 更新时间:2023-12-02 17:02:04 25 4
gpt4 key购买 nike

rails :'4.2.10'雷:'1.0.1'

我正在处理一个非常简单的关系,其中 Conversation 有许多 ConversationMessages。我在索引上显示这些 Conversation 记录,并希望根据具有最新 ConversationMessage 的记录对它们进行排序。这就是事情变得有趣的地方。

def index
@conversations = current_user.conversations.includes(:conversation_messages).order("conversation_messages.created_at DESC").page(params[:page])
end

发生的事情是,当我使用 conversation_messages.created_at 进行订购时,大部分记录都没有显示在 View 中,事实上,分页完全消失了;然而,如果我将 ?page=3 附加到 url,您仍然可以访问其他页面;他们每个人的记录数量都非常有限。

此外,如果我删除 .page(params[:page]) 并摆脱分页,所有结果都会显示我是按 Conversation 日期还是 ConversationMessage 日期。

只是当同时使用 ConversationMessage 和分页进行排序时,一切似乎都变得一团糟。

有什么想法吗?

最佳答案

查询适用于joins 而不是includes。您可以通过单个查询来完成:

@conversations = current_user.conversations
.select('conversations.*, max(conversation_messages.created_at) as recent_message_date')
.left_joins(:conversation_messages).group('conversations.id').order('recent_message_date desc')

这会产生预期的结果,但并不可靠。例如,如果您这样做:

>> @conversations.count

您会得到一个错误,因为 ActiveRecord 会将 select 子句替换为您不想要的内容。调用 size 会产生不同的 SQL,但也会导致错误。

要做到这一点,您需要使用子查询。您可以通过使用 ActiveRecord 鲜为人知的 #from 在 Rails 环境中执行此操作方法。这允许您生成一个子查询,然后对该子查询进行操作,例如,通过对其进行排序或使用 where 子句进行过滤。

>> subquery = current_user.conversations
.select('conversations.*, max(conversation_messages.created_at) as recent_message_date')
.left_joins(:conversation_messages)
.group('conversations.id')

子查询 现在是一个 ActiveRecord 关联,其中包含您想要的 conversation 对象,每个对象都有一个暂定的 recent_message_date 属性。我说暂定是因为(如前所示)只有当 ActiveRecord 不决定与我们的 select 子句混淆时,该属性才存在。

为了一成不变,我们必须给子查询一个名称(您要使用表的名称以避免出现问题),然后从子查询中获取所有内容。然后我们可以对结果记录进行计数,我们也可以可靠地根据该属性进行排序或过滤:

>> @conversations = Conversation.from(subquery, :conversations)
.order('recent_message_date desc')

为了让事情变得整洁,我们可以创建一两个方法:

class Conversation < ApplicationRecord
def self.with_recent_message_date
select('conversations.*, max(conversation_messages.created_at) as recent_message_date')
.left_joins(:conversation_messages)
.group('conversations.id')
end

def self.most_recent_first
order('recent_message_date desc nulls last')
end
end

或者,如果您愿意,可以将方法编写为类的作用域;结果是一样的。现在您可以编写清晰、富有表现力的查询:

>> subquery = current_user.conversations.with_recent_message_date
>> @conversations = Conversation.from(subquery, :conversations).most_recent_first

此外,您可以使用新属性添加过滤器或其他任何东西:

>> @conversations.where('recent_message_date > ?', Time.current - 3.days)

你应该能够可靠地分页这个结果。我已经使用 will_paginate 尝试了类似的查询,它按预期工作。

关于ruby-on-rails - 按带分页的关联模型排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53656892/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com