Simple Pagination with Rails

Tuesday, 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.


Motionspire Beta Launch - We Need Your Help!

Sunday, October 19th, 2008

We recently launched the Motionspire beta. We’ve been developing this site for quite some time, and we’re finally opening it up to some users.

The concept behind Motionspire is very simple- we built the site to be the best place to view inspirational motion graphics content. Taking a cue from the CSS gallery concept, which has been implemented well by sites like cssmania, cssremix, and stylegala, among others, we thought that there should be a website where you can go to simply view some good motion graphics.

Instead of doing a full launch, we decided to start off with a beta model, for several reasons. First, it gives us a chance to get some good feedback from beta users before we go ahead with the global launch. We are always open to suggestions to make this site better for its users. Second, the beta launch gives us a chance to track some statistics so we can accurately gauge the resource requirements we’ll need for the site.

With that in mind, we need your help. If you are interested in this project, head on over to motionspire.com and fill out a beta account. It’s really easy, and it will give you the chance to be one of the first to try out this new endeavor. Thanks!


A New Day

Sunday, October 12th, 2008

You may have noticed things are looking a little different around here. We’ve launched our site redesign so please be a little patient in the next few days as we work out the kinks. We’re in the process of launching some really great new content as well. So stay tuned.