强制 ActiveRecord 计算不同值(使用 Kaminari)

发布于 2024-11-23 20:30:19 字数 1172 浏览 3 评论 0原文

我正在使用 Kaminari 对查询的一些结果进行分页,在查询中我选择了不同的记录。考虑以下控制器代码:

@things = Thing.joins... # create a complex query that produces duplicate results

# I want to select distinct results: this produces the correct results
@things = @things.select("DISTINCT things.*")

# when Kaminari calls count, it will run "SELECT COUNT(*)", instead of 
# "SELECT COUNT(DISTINCT things.*)" we will get the wrong count and extra pages
@things = @things.page(params[:page]).per(10)

我能想到的最佳解决方案是传递 :distinct =>; truecount,如此拉取请求,被 Kaminari 的开发者拒绝了。 这个问题讨论了根本问题。 这行代码是对 count 的违规调用。

是否有任何解决方法可以为 Kaminari 提供正确的计数而不涉及修补 Kaminari?谢谢。

更新:

  • 使用名为“count”的范围是一个很好的建议,但在 ActiveRecord::Relation 上调用时不起作用。当调用我的模型类时它可以工作,但这没有帮助。

I'm using Kaminari to paginate some result from a query in which I'm selecting distinct records. Consider the following controller code:

@things = Thing.joins... # create a complex query that produces duplicate results

# I want to select distinct results: this produces the correct results
@things = @things.select("DISTINCT things.*")

# when Kaminari calls count, it will run "SELECT COUNT(*)", instead of 
# "SELECT COUNT(DISTINCT things.*)" we will get the wrong count and extra pages
@things = @things.page(params[:page]).per(10)

The best solution that I can think of is to pass :distinct => true to count, like in this pull request, which was rejected by Kaminari's developer. This SO question discusses the underlying problem. This line of code is the offending call to count.

Are there any workarounds that will provide Kaminari with the correct count that don't involve patching Kaminari? Thanks.

UPDATE:

  • Using a scope called "count" is a great suggestion but doesn't work when called on an ActiveRecord::Relation. It works when called on my model class, but that doesn't help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

回忆躺在深渊里 2024-11-30 20:30:19

请参考以下网址。

https://github.com/amatsuda/kaminari/pull/77

https://github.com/tbeauvais/kaminari/commit/23695cbdc4ff1b9fa58c18d4a3c2f18e21451b8b
但是,他们在 Rails 3.1.0 上失败了。

对于 Rails 3.1.0,创建 Rails.root/initializers/kaminari_for_distinct.rb。
并使用以下代码。

module Kaminari
  module ActiveRecordRelationMethods
    extend ActiveSupport::Concern
    module InstanceMethods
      def total_count #:nodoc:
        if distinct_column_name.nil?
          c = except(:offset, :limit).count
        else  
          c = except(:offset, :limit).count(distinct_column_name, :distinct => true)
        end
        # .group returns an OrderdHash that responds to #count
        c.respond_to?(:count) ? c.count : c
      end

      # Get the column name used in distinct query.
      # This could have been set on the Model class, or the ActiveRecord::Relation 
      def distinct_column_name
        @distinct_column || distinct_column
      end
    end
  end
end

module Kaminari
  module ConfigurationMethods
    extend ActiveSupport::Concern
    module ClassMethods

      # Set the name of the column to use during .count()
      # Setting this will cause call to count to use: count(:id, :distinct => true) for all the Models paged queries. 
      # Example:
      #   class User < ActiveRecord::Base
      #     use_distinct :id
      #   end
      def use_distinct(column)
        @distinct_column = column
      end

      # Returns the distinct column name set on the Model, or nil if not using distinct
      def distinct_column
        @distinct_column
      end
    end
  end
end


module Kaminari
  module PageScopeMethods
    extend ActiveSupport::Concern
    module InstanceMethods

      # Set the name of the column to use during .count()
      # Setting this will cause call to count to use: count(:id, :distinct => true)
      # Example: User.page(3).per(5).use_distinct(:id)
      def use_distinct(column)
        @distinct_column = column
        self
      end
    end
  end
end

please refer to the following url.

https://github.com/amatsuda/kaminari/pull/77

https://github.com/tbeauvais/kaminari/commit/23695cbdc4ff1b9fa58c18d4a3c2f18e21451b8b
but ,they faild on Rails 3.1.0.

For Rails 3.1.0, create Rails.root/initializers/kaminari_for_distinct.rb.
And use the following code.

module Kaminari
  module ActiveRecordRelationMethods
    extend ActiveSupport::Concern
    module InstanceMethods
      def total_count #:nodoc:
        if distinct_column_name.nil?
          c = except(:offset, :limit).count
        else  
          c = except(:offset, :limit).count(distinct_column_name, :distinct => true)
        end
        # .group returns an OrderdHash that responds to #count
        c.respond_to?(:count) ? c.count : c
      end

      # Get the column name used in distinct query.
      # This could have been set on the Model class, or the ActiveRecord::Relation 
      def distinct_column_name
        @distinct_column || distinct_column
      end
    end
  end
end

module Kaminari
  module ConfigurationMethods
    extend ActiveSupport::Concern
    module ClassMethods

      # Set the name of the column to use during .count()
      # Setting this will cause call to count to use: count(:id, :distinct => true) for all the Models paged queries. 
      # Example:
      #   class User < ActiveRecord::Base
      #     use_distinct :id
      #   end
      def use_distinct(column)
        @distinct_column = column
      end

      # Returns the distinct column name set on the Model, or nil if not using distinct
      def distinct_column
        @distinct_column
      end
    end
  end
end


module Kaminari
  module PageScopeMethods
    extend ActiveSupport::Concern
    module InstanceMethods

      # Set the name of the column to use during .count()
      # Setting this will cause call to count to use: count(:id, :distinct => true)
      # Example: User.page(3).per(5).use_distinct(:id)
      def use_distinct(column)
        @distinct_column = column
        self
      end
    end
  end
end
白日梦 2024-11-30 20:30:19

我建议在模型上设置一个范围,

但这可能会造成混淆,所以你要小心

范围:count, select("DISTINCT things.*")

有关更多信息,请查看 此处

I would suggest a scope on the Model

This might confuse things though so you want to be careful

scope :count, select("DISTINCT things.*")

For more information look here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文