Заставить ActiveRecord считать разные (с Kaminari) - PullRequest
5 голосов
/ 15 июля 2011

Я использую 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 => true в count, как в этом запросе на получение , который был отклонен разработчиком Kaminari. Этот вопрос SO обсуждает основную проблему. Эта строка кода является вызывающим вызовом count.

Существуют ли какие-либо обходные пути, которые обеспечат Каминари точным подсчетом, который не включает исправление Каминари? Благодарю.

UPDATE:

  • Использование области действия с именем count является отличным предложением, но не работает при вызове ActiveRecord :: Relation. Он работает при вызове в моем классе модели, но это не помогает.

Ответы [ 2 ]

3 голосов
/ 02 сентября 2011

пожалуйста, обратитесь к следующему URL.

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
0 голосов
/ 15 июля 2011

Я бы предложил область действия на модели

Это может привести к путанице, поэтому вы должны быть осторожны

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

Для получения дополнительной информации смотрите здесь

...