Recipe 5.2. Displaying Large Datasets with Pagination


Problem

Displaying large datasets in a browser can quickly become unusable; it can even cause the browser application to crash. On the server side, loading in large datasets just to display a few rows can play havoc with your server performance. You want to manage the display of large datasets by paginating the output: displaying subsets the output of over multiple pages.

Solution

The paginate helper makes setting up pagination simple. To paginate the output of a large list of movies, call the pagination method in the Movies Controller and store the results in two instance variable named @movie_pages and @movies:

app/controllers/movies_controller.rb:

class MoviesController < ApplicationController   def list     @movie_pages, @movies = paginate :movies,                                       :order => 'year, title',                                      :per_page => 10   end end

In your view, iterate over the array of Movie objects stored in the @movies instance variable. Use the @movie_pages Paginator object to create links to the next and previous page of results. Include the pagination_links method in your view to display links to other pages of results.

app/views/movies/list.rhtml:

<table width="100%">   <tr>   <% for column in Movie.content_columns %>     <th>           <span style="font-size: x-large;"><%= column.human_name %></span>     </th>      <% end %>   </tr>   <% for movie in @movies %>     <tr style="background: <%= cycle("#ccc","") %>;">     <% for column in Movie.content_columns %>       <td><%=h movie.send(column.name) %></td>      <% end %>     </tr>      <% end %>   <tr>     <td colspan="<%= Movie.content_columns.length %>">       <hr />         <center>         <%= link_to '[previous]', { :page => @movie_pages.current.previous } \             if @movie_pages.current.previous %>         <%= pagination_links(@movie_pages) %>         <%= link_to '[next]', { :page => @movie_pages.current.next } \             if @movie_pages.current.next %>       </center>     </td>      </tr> </table>

Discussion

Pagination is the standard technique for displaying large result sets on the Web. Rails handles this common problem by splicing up your data into smaller sets with the paginate helper.

Figure 5-2 shows the output of the pagination from the solution.

Figure 5-2. The fourth page of a paginated list of movies


Calling paginate in your controller returns a Paginator object, as well as an array of objects that represents the initial subset of results. The current page is determined by the contents of the params['page'] variable. If that variable is not present in the request object, the first page is assumed.

The options passed to paginate specify the model objects to fetch and the conditions of the result set you want paginated. In the solution, the first argument passed to paginate is :movies, which says to return all movie objects. The :order option specifies their order. The :per_page option is the maximum number of records that each page of results should contain. It's common to have this value adjustable by the user. For example, to use the page size value in params[:page_size], do this:

def list   if params[:page_size] and params[:page_size].to_i > 0     session[:page_size] = params[:page_size].to_i   elsif session[:page_size].nil?     session[:page_size] ||= 10   end   @movie_pages, @movies = paginate :movies,                                     :order => 'year, title',                                    :per_page => session[:page_size] end

With this code, a URL of http://localhost:3000/movies/list?page=2&page_size=30 would set the page size to 30 for that session.

In addition to :order, paginate can use all the normal finder options (e.g., :conditions, :joins, :include, :select) plus a few more less common ones.

See Also

  • Rails API documentation for ActionController::Pagination, http://www.rubyonrails.org/api/classes/ActionController/Pagination.html




Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net