导轨 | Kaminari:如何限制最大页数?

问题描述 投票:0回答:1

我使用 Kaminari gem 进行分页。

尝试运行此类代码时出现异常:

Distributor.all.page(123123213213132113322)

=> ActiveRecord::StatementInvalid (Mysql2::Error: 你的 SQL 语法有错误;检查与你的 MySQL 对应的手册 服务器版本,以便在附近使用正确的语法 '3078080330328302833025' 在第 1 行:SELECT

distributors
.* FROM
distributors
限制 11 偏移 3078080330328302833025)

我已经尝试将此类配置添加到初始化程序中,但没有帮助:

Kaminari.configure do |config|
  config.max_pages = 1000000000
end

#page
方法调用上强制限制最大页数的正确方法是什么,或者是否有其他方法可以避免此类异常?

mysql ruby-on-rails ruby pagination kaminari
1个回答
2
投票

您可能会遇到未记录的 MySql 偏移量限制

3689348814741910324
— AKA
3_689_348_814_741_910_324
AKA
3,689,348,814,741,910,324
AKA
((2^65) / 10) + 1)
AKA
((2**65) / 10) + 1

我在编写 Graphiti 支持的 API 时遇到了同样的事情。

我是这样处理的。我确信这里会有一些有用的金块。 具体来说,您可以编写自己的分页助手来包装 Kaminari 页面调用,该调用应用一些过滤,就像我在下面所做的那样。 (我救援/捕获引发的错误并将其作为信息性消息发送回用户。)

class ApplicationResource < Graphiti::Resource

  ###################################################################
  #
  # Constants
  #
  ###################################################################

  # Exceeding this integer value in a query causes MySQL to overflow the integer, typically raising an error.
  # I found very little information about this limit online. I discovered it using trial and error, otherwise I'd
  # explain more.
  MYSQL_QUERY_INT_MAX = 3_689_348_814_741_910_324 # ((2**65) / 10) + 1

  CURRENT_PAGE_DEFAULT = 1 # Graphiti takes care of this behavior itself internally. This constant is for reference only.
  CURRENT_PAGE_MIN     = 1
  CURRENT_PAGE_MAX     = MYSQL_QUERY_INT_MAX

  RESULTS_PER_PAGE_DEFAULT = 20
  RESULTS_PER_PAGE_MIN     = 1
  RESULTS_PER_PAGE_MAX     = 250



  ###################################################################
  #
  # Pagination
  #
  # The `scope` draws from and builds upon the `base_scope` provided by the child resource.
  # The `current_page` and `results_per_page` come from the request
  # params in the format: /resources?page[number]=2&page[size]=10
  #
  ###################################################################
  self.default_page_size = RESULTS_PER_PAGE_DEFAULT # Override default from Graphiti::Resource which is 10.
  self.max_page_size     = RESULTS_PER_PAGE_MAX     # Override default from Graphiti::Resource which is 1,000.

  paginate do |scope, current_page, results_per_page|

    # Apply defaults if the respective parameters are omitted.
    # No need to check current_page as Graphiti internally enforces a default value (1).
    results_per_page = RESULTS_PER_PAGE_DEFAULT if results_per_page.nil?

    # Guard against invalid parameters.
    # No need to guard against RESULTS_PER_PAGE_MAX as Graphiti does that on its own via the max_page_size setting above.
    if results_per_page < RESULTS_PER_PAGE_MIN
      raise(Api::UnsupportedPageSizeMin.new(results_per_page, RESULTS_PER_PAGE_MIN))
    end
    if current_page < CURRENT_PAGE_MIN || current_page > CURRENT_PAGE_MAX
      raise(Api::InvalidPageNumber.new(current_page, CURRENT_PAGE_MIN, CURRENT_PAGE_MAX))
    end

    # Perform pagination (makes use of the kaminari gem).
    scope.page(current_page).per(results_per_page)
  end
© www.soinside.com 2019 - 2024. All rights reserved.