Twitter RSS

Simple Pagination with Rails

by Brett Wejrowski on May 5th, 2009

While I was developing Motionspire, I needed to implement a pagination system for the video content.  I looked through the existing plugins, but found that I really desired something extremely simple and custom to work within my search controller.  With only a few lines of code, I created a very basic system for managing pagination that can be ported to other sites with ease.

The Search Controller

The Motionspire search controller uses one function and view for returning any content, whether it’s filtered or not, so the pagination only required one copy of the code to be implemented.  I keep a session variable for maintaining the user’s preference for items per page, and if that parameter has been sent to the search function I set the session variable :


if params[:itemsPerPage] then session[:itemsPerPage] = params[:itemsPerPage] end

When I run though the search function, I see if a page parameter has been passed:


if params[:page] then @page = params[:page].to_i else @page = 1 end

After I retrieve the articles pertaining to the search parameters (in this case the results are stored into an array called @videos), I check the :itemsPerPage preference and find the last possible page:


if session[:itemsPerPage] then @per = session[:itemsPerPage].to_i else @per = 24 end

@lastpage = @videos.length/(@per) + 1

if @videos.length%(@per) == 0

    @lastpage = @lastpage - 1

end

I have a default itemsPerPage value of 24 hardcoded, and you can change this for your search.

From here, we simply return the search results for that page, using the current page and the items per page preference:


@videos = @videos[((@page-1)*@per),@per]

For search queries within a large data set, I would recommend using these parameters with the sql query with the ‘ORDER BY’ and ‘LIMIT’ in order to avoid returning extremely large results unnecessarily.

The Helper

First, I created a short helper function that finds the min and max pages, ensuring we don’t show a negative page or a page that doesn’t exist:


def minmaxpage(current,total,option)
    min = current - 2
    if min < 1
        min = 1
        max = 1 + 4
        if max > total then max = total end
    end
    max = min + 4
    if max > total
        max = total
        min = max - 4
        while min < 1
            min = min + 1
        end
    end
    if option == 'min' then return min else return max end
end

The View

For the content from the view, we use the @videos array to present the content for the page.  The only custom coding necessary is in the links for the pages.  For this site, I provide a first and last page link, along with 2 pages on either side of the current page.  You can manipulate this code how you want, but the basic idea will remain the same.

First we grab the min and max page from the helper:


<% min = minmaxpage(@page, @lastpage, 'min') %>

<% max = minmaxpage(@page, @lastpage, 'max') %>

For the code for the page links, we simply check to see if the min page is within two of the current:


<% if min < @page %>

    <%= link_to( "Prev",

        :action => "search",

        :page => (@page - 1) ) %>

<% end %>

<% if min > 1 %>

    <%= link_to( "1",

        :action => "search",

        :page => 1 ) %>

<% end %>

<% x = min %>

Then we loop through the remaining pages, ensuring we don’t go over the max, and make the current page simple text instead of a link:


<% while x <= max %>

    <% if x.to_i == @page.to_i %>

        <span class="current"><%= x %></span>

    <% else %>

        <%= link_to( x.to_s,

            :action => "search",

            :page => x ) %>

    <% end %>

    <% x = x+1 %>

<% end %>

<% if max < @lastpage %>

    <%= link_to( @lastpage.to_s,

        :action => "search",

        :page => @lastpage ) %>

<% end %>

<% if max > @page %>

    <%= link_to( "Next",

        :action => "search",

        :page => (@page + 1) ) %>

<% end %>

The code may look a little long, but the implementation took very little time.  I know exactly what the code is doing and it is very easy to expand this for different situations and code.

There are a lot of solutions for pagination of content, but I found that this simple implementation helped me avoid using plugins and save time.  Let me know if you guys have any questions or comparable solutions.


Tags:
Posted in Motionspire, Programming 5 Comments »


5 Responses to Simple Pagination with Rails

Leave a Comment
  1. random8r  May 5, 2009

    I noticed you’ve added that you recommend using limit and offset… but I still stand by what I said… paginator is a better choice. (IMHO). More flexible, and not that much more code. More RUBY-like.

  2. I’m sorry to say this, but this is not exactly a good example for pagination or ruby programming in general. If you really want to roll your own solution, you should at least try to keep your views clean and simple and move this conditional code into a helper.

    But why don’t you use what’s already there? will_paginate is a nice and simple solution for pagination. In your controller, you could write ‘@page = @videos.paginate :per_page => 10, :page => params[:page]‘

    In your view, use the pagination_helper like this:
    ” This will render the pagigation links, and there are a lot of options to customize it.

    Concerning limit and offset: Using those is an absolute must to get reasonable performance. And, best of all: will_paginate uses them if you paginate active_record queries automatically!

  3. srivatsav  May 19, 2009

    I am using will_paginate but i could not remove the page numbers. I do not want the page numbers. how to do that?

  4. I needed a simple solution to paginage an array of results returned from an xml feed. This solution worked perfectly w/out needing to use any plugin, etc., in my rail app. Nice job!

  5. It’s obviously really expensive, but if you get funding, it’s a great place. ,

Join the Discussion