Will Paginate Gem适配Elastic Search数组:自定义总页数解决分页报错
Absolutely! You can absolutely use will_paginate with your Elasticsearch results—you just need to give the gem the total number of entries it needs to calculate pagination metadata like total_pages. Here's how to fix that error and get pagination working smoothly:
The root issue here is that will_paginate expects the object it receives to respond to pagination-specific methods (like total_pages, current_page). Plain Ruby arrays don’t have these methods by default, but will_paginate has a built-in extension to handle arrays, and we can feed it the total number of matching documents from Elasticsearch to make everything work.
Step 1: Load the will_paginate Array extension
First, add this line to your Gemfile (then run bundle install) or to an initializer file (like config/initializers/will_paginate.rb):
require 'will_paginate/array'
This adds pagination capabilities directly to Ruby arrays.
Step 2: Capture total results from Elasticsearch
When you run your Elasticsearch query, grab the total number of matching documents. The exact syntax depends on your Elasticsearch client version:
- For Elasticsearch v7+ (newer clients):
response = YourModel.search(your_query) total_entries = response.hits.total.value - For older Elasticsearch versions:
total_entries = response.total
Step 3: Paginate your array with explicit total entries
Instead of passing the raw array to will_paginate, use the paginate method on your results array, and pass the total_entries parameter with the value you pulled from Elasticsearch:
# In your controller action @data = response.results.to_a.paginate( page: params[:page], per_page: 10, # Adjust this to your preferred items per page total_entries: total_entries )
Step 4: Use will_paginate in your view as normal
Now @data is wrapped in a WillPaginate::Collection object that has all the methods the gem needs. Your original view code will work without errors:
<%= will_paginate @data %>
Why this works
The will_paginate/array extension adds a paginate method to arrays that converts them into a WillPaginate::Collection. This object includes all the pagination metadata methods (like total_pages)—and by passing total_entries, you tell it the full count of results from Elasticsearch, so it can calculate total pages, next/previous links, etc., correctly.
Alternative: Manually create a WillPaginate::Collection
If you prefer a more explicit approach, you can directly instantiate the collection instead of using the array extension:
@data = WillPaginate::Collection.create(params[:page], 10, total_entries) do |pager| pager.replace(response.results.to_a) end
This achieves the same result, but using the array extension is more concise for most cases.
内容的提问来源于stack exchange,提问作者Barath Kumar

