Ruby 板


LINE

我现在还是不太明白为什麽 rails 2 要拿掉 paginate? 只是听说该 paginate 做得很差,所以要拿掉? 为什麽不是改善而是拿掉?分页的系统难道有问题吗? 但我仍然需要 paginate. 最常被提起的大概是 will_paginate 吧。 不过我讨厌同样的需求却要一直换东西,又更讨厌用被建议不要使用的东西。 後来我看到了 gem paginator: http://paginator.rubyforge.org/ 我承认我不喜欢 plugin, 因为 rails 的东西不等於 ruby 的东西。 如果可以的话,我只想用 rubygems 发布的东西,其他都不想用。 所以我先试了这个 gem 版的 paginator. 试了之後,我发觉其实他原理根本就很单纯,单纯到乾脆自己写一个 最符合自己使用习惯的也花不了多少时间。所以後来我随手写了一个, 目前是放在 ludy 里面,毕竟全程式码也没多少,为此开个专案感觉怪怪的? Ludy::RailsPaginator: http://ludy.rubyforge.org/classes/Ludy/RailsPaginator.html 用法: pager = Ludy::RailsPaginator.new PokeActionLog, :conditions => ['poker_id = ? OR pokee_id = ?', self.id, self.id ], :order => 'created_at DESC' pager.per_page = 20 第一个参数是要被分页 model 的 class, 这里是 PokeActionLog, 第二个参数是一个 hash, 这个 hash 会分别传给 counter 和 fetcher. 所谓 counter 和 fetcher 是来自其 parent, Ludy::Paginator. Ludy::Paginator: http://ludy.rubyforge.org/classes/Ludy/Paginator.html 基本上 RailsPaginator 只是这个东西的简单 wrapper, 另外还有 ArrayPaginator, 这比较容易理解,以这个当例子。 Ludy::ArrayPaginator: http://ludy.rubyforge.org/classes/Ludy/ArrayPaginator.html 所谓 counter 就是取得总数的 function, 而 fetcher 就是取得资料的 function. 在 array 中,counter 就是 Array#size, 而 fetcher 当然就是 Array#[]. call fetcher 时会有两个参数,一个是 offset, 另一个是 per_page. 对 array 来说,这就是 array[offset, per_page]. 从 offset 的地方取出 per_page 个资料。 所以 ArrayPaginator 的实作是这样: class ArrayPaginator < Paginator attr_reader :data def initialize data @data = data super(lambda{ |offset, per_page| @data[offset, per_page] }, lambda{ @data.size }) end end 非常单纯。 RailsPaginator 用一样的概念: class RailsPaginator < Paginator attr_reader :model_class def initialize model_class, opts = {} @model_class = model_class super(lambda{ |offset, per_page| @model_class.find :all, opts.merge(:offset => offset, :limit => per_page) }, lambda{ @model_class.count opts }) end # it simply call super(page.to_i), so RailsPaginator also eat string. def page page; super page.to_i; end alias_method :[], :page end 至於最下面那个 page method, 只是为了方便,使得: pager.page 1 和 pager.page '1' 等价 这样做的原因是 params 来的东西都是字串,to_i 既然经常会用到,乾脆就帮忙做掉。 另外,paginator 本身 include Enumerable, 是为 pages 的集合。 page 本身没有 include Enumerable, 不过 method_missing 会将所有的 method delegate 给那页资料的 array, 所以是资料的集合。 最後我写在 controller 的东西是这样: log_page = @target_user.log_page(params[:page] || 1) @current_page = log_page.page # 第?页 @next_page = log_page.next.ergo.page # 下一页的 page instance @prev_page = log_page.prev.ergo.page # 上一页的 page instance # p.s. ergo 很好用... 可以少写很多判断 @last_log = log_page.end + 1 # 这一页的最後一笔是第?笔 @first_log = log_page.begin + 1 # 这一页的第 一笔是第?笔 @log_count = log_page.pager.count # 总共有几笔? # 每一个 log 要做额外处理 @logs = log_page.to_a.map{ |l| l.prepare_message(@target_user); l } * 我之所以会把 counter 和 fetcher 拆成外部传入的 function, 是希望 pager 本身能成为一个能重复利用的 instance. 只要设定好 counter 和 fetcher, 接着不管资料怎麽变动, 都用同一个 pager 就好了。就算真的改变了,一样可以再改写: pager.counter = lambda{ another_thing.count :conditions => [...] } pager.fetcher = lambda{ yet_another_thing.find :all } 当然这样是不对称啦。目前我是还没写类似这样的: rails_pager.opt = :conditions => [...], :order => 'created_at DESC' 或是 rails_pager.model = AnotherModel 不过这要加上去都是轻而易举的。嗯,既然提到了,等会就来加好了... * 只是不知道 rails paginate 拿掉的原因,所以做这东西也不知道是否真的有用? 反正当练练基本功也没什麽不好就是了,我一直是这样觉得。全部的程式也没几行。 test case 在这: require 'ludy/paginator' require 'ludy/symbol/to_proc' if RUBY_VERSION < '1.9.0' class TestPaginator < Test::Unit::TestCase def self.data; @data ||= (0..100).to_a; end def for_pager pager # assume data.size is 101, data is [0,1,2,3...] pager.per_page = 10 assert_equal 11, pager.size assert_nil pager[0] assert_equal((0..9).to_a, pager.page(1).to_a) assert_equal((10..19).to_a, pager[2].to_a) assert_equal(20, pager.page(3).first) assert_equal((90..99).to_a, pager[10].to_a) assert_equal([100], pager.page(11).to_a) assert_nil(pager.page(12)) assert_equal(pager[1], pager[2].prev) assert_equal(pager.page(11), pager[10].next) assert_nil(pager[1].prev) assert_nil(pager[10].next.next) assert_equal pager[4].data, pager[4].fetch assert_equal(pager[1], pager.pages.first) assert_equal(pager[2], pager.to_a[1]) assert_equal(5050, pager.inject(0){|r, i| r += i.inject(&:+) }) assert_equal 4, pager[4].page assert_equal 10, pager[2].begin assert_equal 19, pager[2].end assert_equal 100, pager[11].end end def test_basic pager = Ludy::Paginator.new( lambda{ |offset, per_page| # if for rails, # Data.find :all, :offset => offset, :limit => per_page TestPaginator.data[offset, per_page] }, lambda{ # if for rails, # Data.count TestPaginator.data.size }) for_pager pager end def test_offset_bug a = (0..9).to_a pager = ArrayPaginator.new a pager.per_page = 5 assert_equal 5, pager[1].size assert_equal 5, pager[2].size assert_nil pager[3] end class Topic class << self def count opts = {} 101 end def find all, opts = {} TestPaginator.data[opts[:offset], opts[:limit]] end end end def test_for_rails for_pager Ludy::RailsPaginator.new(Topic) end def test_for_array for_pager Ludy::ArrayPaginator.new(TestPaginator.data) end end -- By Gamers, For Gamers - from the past Interplay --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.128.121.85
1F:推 janyfor:rails 2.0 是不是拿掉了不少 rails 吸引人的东西阿? 02/18 18:28
2F:→ poga:没有 02/18 19:33







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:iOS站内搜寻

TOP