在记录集合上使用 will_paginate 会更改分页结果计数?

Posted

技术标签:

【中文标题】在记录集合上使用 will_paginate 会更改分页结果计数?【英文标题】:Using will_paginate on a collection of records changes the paginated results count? 【发布时间】:2022-01-06 12:14:08 【问题描述】:

我们有型号SubscriptionSubscriptionCart。一个Subscriptionhas_manySubscriptionCart

我们拥有并使用这两个模型之间的关系来获得 Subscription 最旧的购物车,其中 plan_id 更改为当前的 Subscription plan_id(换句话说,定义当前的第一个购物车Subscription计划)

Subscription 关系如下:

has_one     :first_version_with_current_plan, -> 
    joins(:subscription)
      .where(subscription_carts:  status: "processed" )
      .where("subscription_carts.plan_id = subscriptions.plan_id")
      .order("subscription_carts.authorized_at ASC")
  , class_name: "SubscriptionCart", inverse_of: :subscription

上述关系将返回一个Subscription(父级)和第一个购物车(子级),其中plan_id 更改为Subscription plan_id 是什么。

我们在索引视图中使用该关系,我们使用will_paginate 来显示结果。

控制器:

  def index
    @subscriptions = current_account.subscriptions
      .includes(:first_version_with_current_plan)
      .order("subscription_carts.authorized_at ASC") # relation attribute
      .paginate(page: params[:page], per_page: 20)
      
  end

问题我们遇到的问题是,在 .paginate 方法之前,@subscriptions.count 将返回 50,但将 .paginate 应用于集合会在视图中呈现少于 10 个总结果。

我怀疑will_paginate 在幕后进行了第二次查询,这会破坏结果计数,但我不确定,因为我在网上找不到太多信息。

对此有任何解释或任何已知的解决方法吗?

【问题讨论】:

【参考方案1】:

分页应该改变计数 - 重点是通过应用限制和偏移来限制从数据库中获取的数据量。分页时,计数始终等于或小于 per_page 设置 - 毕竟您只是从表中获取那么多行。

如果您想计算记录总数,您需要在没有分页的范围内创建单独的计数查询:

def index
  scope = current_account.subscriptions
    .includes(:first_version_with_current_plan)
    .order("subscription_carts.authorized_at ASC")
  @count = scope.count
  @subscriptions = scope.paginate(page: params[:page], per_page: 20)
end

如果您想计算记录总数,您需要在没有分页的范围内创建单独的计数查询,或者在模型上使用计数器缓存。

【讨论】:

我认为我的解释不正确。我知道在使用will_paginate 时,count 将返回与per_page 参数一样多的记录,因为这是页面中“适合”的内容。我遇到的问题是分页前后的结果不一样。如果 @subscriptions 的总大小为 50 条记录,则在该集合上使用 .paginate 会将记录总数更改为 10 或更少。所以 50 条记录变得少于 10 条,好像查询完全不同。 换句话说,我在控制台上运行相同的查询并获得 50 个结果,但应用 .paginate 会显示 10 条记录中的 10 条记录,而不是 3 页的 20、20 和 10 个结果。这就是为什么我认为第二个查询正在幕后发生。 如果您有 50 条记录和 20 页限制并且在第 3 页上,则您有 OFFSET 40 LIMIT 20 所以它完全符合逻辑,您得到 10 的计数。它不会创建 3 个不同的查询作为那将是非常无效的。 我意识到标题中的问题有点误导。错误的不仅仅是count。这是在集合上应用.paginate 后返回的整个数据集。如果范围在控制台上返回 50 条记录,我希望对其应用分页会导致相同的记录根据 per_page 参数划分为所需的页数。但我得到的是与我在控制台上得到的完全不同的记录数据集,最明显的是分页结果的总数少于我在控制台上得到的总数。 编写一个模型测试来复制您期望得到的结果。但我仍然认为你把它弄反了。分页实际上并没有给你分成页面的结果——它只是根据预先计算的偏移量给你那个页面。要获取其他页面,您需要执行更多查询。

以上是关于在记录集合上使用 will_paginate 会更改分页结果计数?的主要内容,如果未能解决你的问题,请参考以下文章

在 Rails 中使用 will_paginate 和 AJAX 实时搜索和 jQuery

Rails 5.2 上 jquery DataTables 和 will_paginate gem 的分页问题

使用 will_paginate 对多个分页页面进行排序

使用will_paginate和Rails时显示部分结果

使用 will_paginate gem 在 Rails 3.2.3 中调用 Ajax

Rails 3 分页,will_paginate 与 Kaminari