Search code examples
ruby-on-railssolractiveadminransack

Pagination for custom solr filter in active admin


I have a custom ransack filter for active admin:

# app/admin/user.rb
filter :by_solr_in, :as => :string

that uses solr for search:

# app/models/user.rb
ransacker :by_solr, formatter: -> (v) {
  ids = UserSearch.all({params: {q: v}, state: :all}).results.map(&:id)
  ids.present? ? ids : nil
} do |product|
  product.table[:id] # i think collection shoud be paginated here
end

Solr (UserSearch.all) gives a collection of all found users as ids, and product.table[:id] takes users with those ids from db. The problem is that there is no pagination. Active admin displays only proper page, but with each page the whole collection is taken from db. How can I correct this?

I tried to pass page to solr in before_filter and use it there, but if solr gives only 1 page, active admin gets only 1 page.

ids = UserSearch.all({params: {q: v['q'], page: v['page'], per_page: 30}, state: :all}).results.map(&:id)

Solution

  • I got it working. It's not perfect solution, but it might help someone.

    In before_filter i set current page for ransacker and remove it from params.

    In ransacker I use this page and get pagination data from SolrPaginatedCollection:

    results = UserSearch.all({params: {q: v, page: page, per_page: 30}, state: :all}).results
    UserSearch.admin_pagination_data = [results.total_pages, results.total_count, page || 1]
    

    In active admin i had to modify collection to display correct page data:

    def collection
      collection = super
      if params['q'].present? && params['q']['by_solr_in'].present? && UserSearch.admin_pagination_data.present?
        collection.define_singleton_method(:total_pages) { UserSearch.admin_pagination_data[0] }
        collection.define_singleton_method(:total_count) { UserSearch.admin_pagination_data[1] }
        collection.define_singleton_method(:current_page) { UserSearch.admin_pagination_data[2] }
      end
      collection
    end