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