paginating_findより早い(と思う)プラグイン作ってみた

一覧表示処理が遅かったんだけど、よくよく見てみるとページネートの処理で遅くなっている模様。
単純にAR.findで取ってくるだけなら、30〜40%早くなる。ついでにページネート用の件数(全件件数)取得のcountをやっても30%くらい早い。
#ちなみにviewでのページネート用のリンク作成ではほとんど時間くっていない。

とりあえずベタ書きで処理はできたんで、じゃあプラグインとして外出ししてみようかということで一応作ってみました^^;
ページングっていうか何件目から何件目を取ってくるところをMySQLに特化してるんでとりあえず「paginating_mysql」って名前にしてみた。


作ったもの。

(参考)
Rails pluginの作り方 - 川o・-・)<2nd life
ちょっと古いけど、基本的にはここに書いてあるように、init.rbとlibの下だけでおkでした。
libの下は、ARを拡張するpaginating_mysql.rbと、viewで使うヘルパーpaginating_helper.rb。


使ってみる。


controller

   currentpage = params[:page]
   page_size = 10
   @page_link_array, @topic_list =Topic.paginate(currentpage, page_size,
      {:include => [:user, :type, :comments, :question_status],
      :joins => :categories,
      :conditions => condition,
      :order => sort_condition}
    )

ARを拡張して、各モデルでpagenateっていうメソッドを使えるようになります。
引数は、現在のページ数とページサイズ、あと、AR.find(:all)のパラメータ。
戻り値に、AR.find(:all)の結果であるモデルの配列と、ページネートのリンク作成用の配列がセットされます。



view

    <div class="paginate">
      <%= paginating_links("wrapper", @page_link_array, 
        {:controller => "topic", :action => "list",
         :category_id => @category_id, :type_id => @type_id,
         :sort_condition => @sort_condition, :narrow_condition => @narrow_condition} ) 
      %>
    </div>

viewでは、paginating_linksというヘルパーが使えます。基本的にこのヘルパーではlink_to_remoteを組み立てるので、そのための情報を引数に設定しています。
第1引数=更新する場所 →link_to_remoteの:updateに設定するやつ。
第2引数=これは独自。controllerのpaginateメソッドで取得した配列。
第3引数=url_option →link_to_remoteの:urlに設定するやつ。controllerとactionとその他パラメータ。





画面表示


ローカルPCでの測定結果
・修正前:2824msec
・修正後:1899msec(修正前比67.2%)

弱点
・基本的にAR.find(:all)やってるだけ(+link_to_remote)なので、AR.find(:all)以外のやつには使えない。タグのfind_tagged_withとか。
:group使えない(今のところ) →直した
・パラメータのチェックとかは、いろいろ手を入れる必要がありそう
・まだあんま使ってないから汎用性は低いかも


キチンと出来たらどっかに公開しようかとも思ったけど、それならpaginating_findを直した方がよかったかも?