The Pug Automatic

Using will_paginate with acts_as_solr

Written June 15, 2007. Tagged Ruby, Ruby on Rails.

Still playing with Solr/acts_as_solr.

The site I'm working on uses will_paginate for pagination. It turned out to be pretty easy to get that working with results from acts_as_solr.

The solution is to add a find_all_by_solr method that wraps find_by_solr and returns the records of the returned SearchResults.

Stick solr_pagination.rb in lib in your Rails project.

# By Henrik Nyh <https://henrik.nyh.se> 2007-06-18.
# Free to modify and redistribute with credit.

# Adds a find_all_by_solr method to acts_as_solr models to enable
# will_paginate for acts_as_solr search results.

module ActsAsSolr
module PaginationExtension

def find_all_by_solr(*args)
find_by_solr(*args).records
end

end
end

module ActsAsSolr::ClassMethods
include ActsAsSolr::PaginationExtension
end

Then ensure that this code is actually run, by adding

require 'solr_pagination'

to config/environment.rb. It wouldn't work at the bottom of that file, so I stuck it just before

Rails::Initializer.run do |config|

If you want to verify that things work so far, (re)start the script/console and try something like SomeModel.find_all_by_solr("foo", {:limit => 5, :offset => 2}).

And that's the plumbing done.

You want a controller action like

count = SomeModel.count_by_solr(params[:query])
@results = SomeModel.paginate_all_by_solr(params[:query], :page => params[:page], :total_entries => count)

and a view like

<dl>
<% @results.each do |result| %>
<dt><%= result.title %></dt>
<dd><%= result.description %></dd>
<% end %>
</dl>

<%= will_paginate @results %>

Note that the :total_entries must be specified explicitly to paginate_all_by_solr. find_all_by_solr isn't a regular finder, so will_paginate can't just do a SQL COUNT.

Update 2007-06-18

Today's 0.9 release of acts_as_solr made things easier. The code above has been updated.

Below is the old 0.8.5 version of solr_pagination.rb, which had to translate :limit and :offset (used by regular ActiveRecord finders) into :rows and :start (used by find_by_solr), and that got the records directly rather than in a records attribute.

# By Henrik Nyh <https://henrik.nyh.se> 2007-06-15.
# Free to modify and redistribute with credit.

# Adds a find_all_by_solr method to acts_as_solr models to enable
# will_paginate for acts_as_solr search results.

module ActsAsSolr
module PaginationExtension

def find_all_by_solr(query, options)
map = {:limit => :rows, :offset => :start}
map.each do |from, to|
options[to] = options[from]
options.delete(from)
end
find_by_solr(query, options)
end

end
end

module ActsAsSolr::ClassMethods
include ActsAsSolr::PaginationExtension
end