EasyTime - Ruby学习笔记
自我介绍
切换风格
订阅我的Blog
博客日历
文章归档...
最新发表...
博客统计...
网站链接...
资源
===========================================================
HowtoPagination
===========================================================

HowtoPagination


A、控制器内的 Pagination

一、简单的 Pagination

首先,要看看 Pagination 帮助方法是否适合你的目的。通常它允许 :include:joins:conditions,和 :order。事实上,它使用 Model.find(:all,*params)来完成它的工作。这可用于你大多数情况。

paginate”返回两个东西:一个 Paginator 对象和一个当前页条目的集合。所以它使用双赋值语法(x,y = painate(z))。不要让这困惑你。

这儿是个例子:

def list

    @item_pages, @items = paginate(:items, 

                  :include     => [:parent_item], 

                 :conditions => ['parent_id = ?', @some_id], 

                        :order         => 'created_on ASC', 

                      :per_page     => 20)

end

当前页由 @params[‘page’] 变量决定。

有关 Pagination 帮助方法更多信息可查阅: http://wiki.rubyonrails.com/rails/pages/PaginationHelper

二、定制 Pagination

内建的 Pagination 方法在你的 find 变得复杂时会有限制。如果你使用 find_by_SQL ,那么你将明确地想考虑直接使用 Paginator 。这不比 Pagination 帮助方法复杂并且没有什么值得害怕的。

你将只需要决定被找到条目的总数量,每页数量,和当前页。然后,你可用它们创建一个 Paginator 的实例。

这儿,你也会想做出个选择。你要更有效率,对 findAll匹配记录,统计它们,然后只显示被找到集合的一个页?或者这会更有效率,对数据库做出两个调用:1)一个被匹配记录的 SQL COUNT 2)只找到当前页显示的记录。第一种途径将只使用你的SQL数据库一次,但我们会得到许多记录。第二个途径将使用你的SQL数据库两次,但每次将只返回一小部分信息。

你必须决定哪种途径适合于你。回答是这依赖于许多因素:你工作的数据库的尺寸,你的服务器的速度,数据库通信量,你的其它SQL调用的效率,你的数据库设计,或者甚至是你的数据库大小。我发现我可以使用第一个途径(找出所有记录)可成功地找出1000个记录你的英里数在变化。你总是可以用第一种途径开始,并在它变慢时轻易地修改它。

这儿是个 one-SQL-trip,用四种简单的步骤获得所有东西的方法。

def list

    # 步骤1:读取并设置你需的变量

    page = (params[:page] ||= 1).to_i

    items_per_page = 20

    offset = (page - 1) * items_per_page

    # 步骤 2:完成你定制find而没有任何种类限制或偏移量

    # 也就是,获取每个页的所有东西,不麻烦 pagination 

    @items = Item.find_with_some_custom_method(@some_variable)

    # 步骤 3:创建一个 Paginator, 第二个变量持有所有页内的所有条目。

@item_pages = Paginator.new(self, @items.length, 

items_per_page, page)

    # 步骤 4:只发送@items的一个子集给视图

    # 这就是魔术开始的地方... 并且你不必完成其它的find

    @items = @items[offset..(offset + items_per_page - 1)]

end

第二个途径也很容易。你只需要两个SQL方法。在步骤2中,你完成一定数量匹配的记录,然后在步骤4内,你只重新取回当前页的记录。注意,那个”offset””items_per_page”将需要与你的模型的定义find方法如 :offset :limit 参数选项合在一起。(查阅Rdoc文档的 find 方法。)

def list

    # 步骤 1:读取并设置你需要的变量

    page = (params[:page] ||= 1).to_i

    items_per_page = 20

    offset = (page - 1) * items_per_page

    # 步骤 2: 替代查找全部,只找count个记录

    @item_count = Item.find_record_count(@some_variable)

    # 步骤 3: 创建一个 Paginator, 第二个变量持有所有页所有条目

@item_pages = Paginator.new(self, @item_count, 

items_per_page, page)

    # 步骤 4: 只查找被请求的 @items 子集

                 @items 

=Item.find_with_some_custom_method

(@some_variable, offset, items_per_page)

end

B、视图内 Pagination

一旦你控制器已经赋值给 @item_pages(一个 Paginator 实例) @items (一个活动记录对象的集合),你就可以准备在你的视图中利用它们。与 paginator 对象工作并不困难。唯一的 catch 是确保你的其它参数被保存并发送给下一页。(你将注意到支架的 pagination并不缺省地完成这些。)

一、前一页和下一页链接

<%= link_to('previous page', 

{:params => params.merge('page' => @item_pages.current.previous)}) 

if @item_pages.current.previous %>

<%= ' | ' if @item_pages.current.previous and 

@item_pages.current.next %>

<%= link_to('next page', {:params => params.merge('page' => @item_pages.current.next)}) 

if @item_pages.current.next %>

二、List of page number links

Pages: 

<% for page in @item_pages -%>

<%= link_to_unless(params[:page].to_i == page.number, 

page.number,  {:params => 

params.merge('page' => page)}) %>&nbsp;

<% end -%><br />

<!-- Or make the unlinked version bold -->

<% for page in @item_pages -%>

    <%= link_to_unless(params[:page].to_i == page.number, page.number, 

            {:params => params.merge('page' => page)})

 {|link_name| "<strong>#{link_name}</strong>"} %>&nbsp;

<% end -%><br />

<!-- Or give both links and non-links CSS class styles -->

<% for page in @item_pages -%>

    <%= link_to_unless(params[:page].to_i == page.number, page.number, 

            {:params => params.merge('page' => page)}, 

            {:class => 'linked_page'}) {|link_name| "<span class="unlinked_page">#{link_name}</span>"} %>&nbsp;

<% end -%><br />

二、Information about the subset being displayed

Displaying <%= @item_pages.current_page.first_item %> through <%= @item_pages.current_page.last_item %> of <%= @item_pages.item_count %> items.

我希望这个 pagination 指南能有帮助。我将试着回答任何问题。

Questions:

  • Q: 如果传递当前页给 paginate 而不使用 @params

  • A: 页可以用你喜欢的任何Rails方式传递,只要你发现@params不适合于你。Session 变量,cookie变量,和flash变量都是可能的。通过@params通常将更好。

  • Q: I don’t like the way paginate handles overflow pages, for example there only 2 pages, I specify page 3, paginate will show page 1 should be page 2

  • A: If you don’t like this behavior you can handle it differently in your controller. Just intercept @params[‘page’], test it for whatever criteria you like and modify it’s value as necessary.

  • Another @params[‘page’] tidbit. If you want to go back to a specific page, after navigating in your app, here’s how to do that. First, put code to this effect into the controller to store the @params[‘page’] into the session MyController#list def list session[:page] = @params[‘page’] end. Second, to link back to this same page, include this in the view <= link_to ‘Back’, :action => ‘list’,:page => session[:page] > Thanks to plasko, who deserves the credit for this solution. —mattyboy

  • Q: How can I populate paginator using find_with_sql() or populate it from an array generated from my own method?

my4java 发表于:2006.05.06 22:37 ::分类: ( Rails散文 ) ::阅读:(1713次) :: 评论 (0) :: 引用 (0)

发表评论
标题

在此添加评论

称呼

邮箱地址(可选)

个人主页(可选)

authimage