We are a user experience design and software development firm
Hire us to design your site, build your application, serve billions of users and solve real problems.
will_paginate is very well designed plugin. Besides ActiveRecord object integration, it can integrate with array and any collection that you may have. The README.rdoc (in version 2.2.2) and wiki clearly and concisely document how to use it with ActiveRecord objects. I recently needed to use it for a collection outside of activerecord and here is how I did it.
My input params supplied the current page and the per_page. So, I had
current_page = params[:page] per_page = params[:per_page] # could be configurable or fixed in your app
1) Fetch your collection:
In case of ActiveRecord object, we would do:
@posts = Post.paginate :page => params[:page], :per_page => 50
In case of non-ActiveRecord, the onus is still on us to fetch just the records that we need. If we can't and we need to work with full collection, will_paginate doesn't mind. So, here we go...
# Non-ActiveRecord Post @posts = Post.perform_search_and_obtain_collection(params[:criteria])
2) IMP*: Create an instance of WillPaginate::Collection class.
@page_results = WillPaginate::Collection.create(current_page, per_page, @results.total_results) do |pager| pager.replace(@posts.to_array) end
WillPaginate::Collection extends Array class and added properties like @current_page, @per_page, @total_entries etc. We pass the current_page, per_page properties in constructor and we replace the array contents by converting our @posts to an array (@posts.to_array). This is assuming that @posts contains only the collection for current-page. If @post contains _all_ results, then we can do following:
@page_results = WillPaginate::Collection.create(current_page, per_page, @results.total_results) do |pager| start = (current_page-1)*per_page # assuming current_page is 1 based. pager.replace(@posts.to_array[start, per_page]) end
If our search results were already an array, then it is even easier. All we do is:
@page_results = @posts.paginate(params[:current_page], params[:per_page])
Yes, the plugin adds a method "paginate" to Array class.
Once we have an instance of WillPaginate::Collection object, it behaves exactly same as the one we normally obtain from ActiveRecord.paginate() function. So, we can continue to do this in viewer:
<ol> <% for post in @page_results -%> <li>Render `results` in some nice way.</li> <% end -%> </ol> <p>Now let's render us some pagination!</p> <%= will_paginate @page_results %>
Also, I encourage you to peek into the source code. I found paginated_section that renders pagination stuff at the top/bottom of page.
<% paginated_section @posts do %> <ol id="posts"> <% for post in @posts %> <li> ... </li> <% end %> </ol> <% end %>
Even the rendering is done using a pluggable class, incase if you want to render page links differently.
Topics: activerecord, pagination, Ruby on Rails, will_paginate
Hire us to design your site, build your application, serve billions of users and solve real problems.
Thanks this is exactly what I need.
Comment by Daniel Lucraft, Thursday, August 28, 2008 @ 7:28 am
Thank you so much. I googled for a whole day, and eventually I found your post. And your method solved all the problems I need to tack! Cheer!
Comment by boblu, Thursday, September 11, 2008 @ 8:57 pm
Yeah I looked for hours before finding this. And it was just what I needed. Thanks alot
Comment by Iain, Tuesday, October 7, 2008 @ 4:11 am
Am I the only one getting the exception: Wrong number of arguments (2 for 1) trying this:
@page_results = @posts.paginate(params[:current_page], params[:per_page])
Thanks!
Comment by shawn, Wednesday, November 26, 2008 @ 8:14 pm
Found it:
http://mislav.uniqpath.com/static/will_paginate/doc/
2.2.0, released 2008-04-07 API changes
Remove old, deprecated style of calling Array#paginate as “paginate(page, per_page)”.
If you want to specify :page, :per_page or :total_entries, use a parameter hash.
Comment by shawn, Wednesday, November 26, 2008 @ 8:16 pm