simple_page
Adds simple but flexible pagination to ActiveRecord as well as the appropriate helpers to render page links.
Part of the core of this works was adapted from the github project paged_scopes.
Install the gem and you are ready to go. In your Gemfile:
gem 'simple_page'
In the Controllers
Use the simple_page helpers - this is only needed if you want to use the standard helpers and are not writing your own.
helper :simple_page
Modify your action to get the current page and set the page size:
def index
@products = Product.where({})
@products.page_size = 10
@page = params[:page] || 1
respond_with(@products)
end
Note the following: Instead of the standard Product.all - which returns an array - I have used Product.where({}) which returns a scope. The following line sets the pagination size, then we set a variable to select the current page (or page 1) depending on the parameters passed to the action.
Lastly we do a normal respond with the @products scope. Very little change to a normal controller method really.
Finding the page number for a known object
Something that I need to do from time to time. Especially when somebody direct links to an object and the pages are displayed within the “show” action
@product = Product.find(params[:id])
@products = Product.where({})
@products.page_size = 10
@page = @products.find_page_number(@product)
This is probably not the most wonderfully efficient thing to do, but it works. Feel free to contact me if you have a better method for implementing this than the one I’ve used.
In the Views
In a view where all of the products would normally be displayed, we now only want to display the products from the selected page. This can be achieved as follows:
<% @products.page(@page).each do |product| %>
...
<% end %>
Then at the bottom we put in page links:
<%= page_links(@products, @page) %>
Extras
As well as having a simple list of page numbers, there are four special or extra tags that can be used in the links: :first, :preview, :next, :last. The function of these should be reasonably self explanitory or you probably wouldn’t be here.
So the standard page_links function could be used like this:
<%= page_links(@products, @page, [:first, :previous, :next, :last]) %>
In the Helpers
Built in Helpers
These helpers should be fairly self explanitory. Better yet you can easily implement your own if you have formatting requirements. This way if you need pagination to appear differently in different parts of your applicaiton, it’s very straight forward to implement your own helpers.
def simple_page_marker(page)
case page
when :previous
return "Previous"
when :next
return "Next"
when :first
return "First"
when :last
return "Last"
else
return page
end
end
def page_links(collection, selected_page, extras = [ :previous, :next ], page_tag_helper = lambda {|page| simple_page_marker(page)})
content_tag :ul, :class => "page_select" do
collection.page_links_generator(selected_page, :inner => 2, :outer => 1, :extras => extras) do |tag, page_number, classes|
content_tag :li, link_to(page_tag_helper.call(tag), params.merge(:page => page_number)), :class => (classes << :page).join(" ")
end
end
end