为什么.order没有在我的查询中执行?

时间:2017-04-26 22:46:19

标签: ruby-on-rails ruby kaminari

我稍微修改了Kaminari的版本以找到我的记录在哪个页面(原始代码在这里:https://github.com/kaminari/kaminari/wiki/FAQ#how-can-i-know-which-page-a-record-is-on):

module KaminariHelper
  extend ActiveSupport::Concern

  # Detecting page number in pagination. This method allows you to specify column name, order,
  # items per page and collection ids to filter specific collection.
  #
  # Options:
  #  * :by - specifies the column name. Defaults to :id.
  #  * :order - specifies the order in DB. Defaults to :asc.
  #  * :per - specifies amount of items per page. Defaults to object model's default_per_page.
  #  * :nulls_last - if set to true, will add "nulls last" into the order.
  #  * :collection_ids - array of ids for the collection of current class to search position in specific collection.
  #    If it's ommited then search is done across all objects of current object's model.
  #
  def page_num(options = {})
    column     = options[:by] || :id
    order      = options[:order] || :asc
    per        = options[:per] || self.class.default_per_page
    nulls_last = options[:nulls_last] == true ? "nulls last" : ""
    operator   = (order == :asc ? "<=" : ">=")

    data = if options[:collection_ids].present?
      self.class.where(id: options[:collection_ids])
    else
      self.class
    end

    # 1. Get a count number of all the results that are listed before the given record/value.
    # 2. Divide the count by default_per_page or per number given as an option.
    # 3. Ceil the number to get a proper page number that the record/value is on.
    (
      data.where("#{column} #{operator} ?", read_attribute(column))
          .order("#{column} #{order} #{nulls_last}").count.to_f / per
    ).ceil
  end
end

然而,当我测试它时出于一些奇怪的原因.order似乎没有被执行。这是rails console中的sql输出:

2.3.1 :005 > email.page_num(by: :sent_at, order: :desc, per: 25, collection_ids: user.emails.ids, nulls_last: true)
   (1.1ms)  SELECT "emails"."id" FROM "emails" WHERE "emails"."deleted_at" IS NULL
 AND "emails"."user_id" = $1  [["user_id", 648]]
   (1.5ms)  SELECT COUNT(*) FROM "emails" WHERE "emails"."deleted_at" IS NULL AND
 "emails"."id" IN (35946, 41741) AND (sent_at >= '2016-01-22 14:04:26.700352')
 => 13

为什么.order未在最终的SQL查询中应用?有没有办法执行它?否则代码没有意义,因为无法保证它会给我正确的页码。

1 个答案:

答案 0 :(得分:0)

Rails在order时忽略了count子句。

而不是依赖于Rails&#39; count方法,尝试手动计算:

 data.where("#{column} #{operator} ?", read_attribute(column))
      .order("#{column} #{order} #{nulls_last}")
      .select('COUNT(*) c').first.c.to_f / per