トップ «前の日記(2005-04-21 (Thu)) 最新 次の日記(2005-04-23 (Sat))» 編集   RSS 1.0 FEED  

Journal InTime


2005-04-22 (Fri) [長年日記]

_ [Rails] pagination

Webアプリケーションでは、リストが長くなった時に複数ページに分けて、 「次へ」「前へ」のようなナビゲーションを行うことが多い。 たとえば、Googleの検索結果みたいな。

これって結構面倒なのだが、Railsではpaginateというメソッドによって 簡単に実装できる。

まずは、コントローラ側のコードに、

def list
  @question_pages, @questions =
    paginate(:question, :per_page => 5,
             :conditions => "category_id = 1",
             :order_by => "date desc")
end

のように書いておく。

paginateの第一引数にはモデルの名前*1、 第二引数には以下のようなオプションを指定できる。

class_name
モデルのクラス名
per_page
一ページあたりの行数
conditions
where句
order_by
order by句
join
join句
parameter
ページ番号を指定するためのパラメータの名前

で、テンプレートに、

<ul>
<% for question in @questions %>
  <li><%=h question.message %>
<% end %>
</ul>
<%= link_to "前へ", { :page => @question_pages.current.previous } if @question_pages.current.previous %>
<%= link_to "次へ", { :page => @question_pages.current.next } if @question_pages.current.next %> 

と書いておけば、後は勝手にやってくれる。これはラクだなあ。

*1  :foo_barみたいな指定から適当にFooBarのようなクラス名に変換されるらしい

_ [Rails] pagination with ajax

さらに、ajaxによるpaginationもできるらしい。 こっちは試してないけど。

_ [Rails] Content-Type の指定方法

なるほど、before_filterでいろいろできるのか。

しかし、jcodeって。 > How To Use Unicode Strings

_ [その他] 子どもの写真

あれ?おこさん写真が元にもどってる?

[ARAKI notesより引用]

実は、最近はランダムに表示してたりします。

_ [Rails] 速度

あまり他の人の参考にはならないけど、手元の「自前なんちゃって フレームワーク+mod_ruby」なプログラムにくらべて、ほぼ同等 (ちょっと機能は劣る)の「Rails+FastCGI」なプログラム(もちろんproduction環境) は二倍くらい遅かった。

普通ならぜんぜん問題ないんだけど、今回はちょっとスピードがいるんだよな。 どうしよう。

ちなみに、

FastCgiConfig -maxClassProcesses 10 -maxProcesses 50 -minProcesses 5

のような設定なのにプロセスが一つしか動いてなかったので、たんにチューニング できてないだけという可能性も高いけど。

ただ、Rails+mod_rubyはRails+FastCGIよりさらに二倍ほど遅かった (DBのコネクションを使い回してなかったりする?)ので、FastCGIのせいではないかも。

あるいは、アプリケーションの処理が軽ければ軽いほど、FastCGIのオーバーへッドが 効いてくるということはあるかもしれない。

_ [Rails] 高速化

プロファイルを取ると、PGconn#execとModule#public_instance_methodsが 上位に来ていた。 前者に関しては、クエリの結果をキャッシュすることでクエリの発行を減らし、 後者に関しては、AppliationController#action_methodsを以下のように再定義して 高速化。

class MyController < AppliationController
  ...

  @@action_methods = public_instance_methods - hidden_actions

  def action_methods
    return @@action_methods
  end
end

これで、自前フレームワーク+mod_rubyの1.5倍程度の実行時間に収まった。 実際には、DBのレコードが増えるともっと差は縮まるだろう。

あと、pagenateは、

select count(*) from foo where bar = 1
select * from foo where bar = 1 order by baz limit 5 offset 0

のように2回SQLを発行するようだが、

select * from foo where bar = 1 order by baz limit 6 offset 0

のように「1ページあたりの行数 + 1」行分をlimitで指定すれば、 「次へ」を表示するべきかどうかがわかるから、クエリの発行を1回で 済ませることができそうだ。

ページ数を表示したり、Googleみたいに各ページへのリンクを表示したり するとなると、また話が違って来るが。

本日のツッコミ(全4件) [ツッコミを入れる]
_ naruse (2005-04-22 (Fri) 20:00)

文字指向の処理が、jcodeライブラリなんですよねぇ。<br>encodeとかencodingとか、そんな名前に変えたいなぁ。<br>メソッド名もjlengthとかでなく、char_lengthに。

_ shugo (2005-04-22 (Fri) 22:08)

というか、m17n化を:)

_ naruse (2005-04-23 (Sat) 00:10)

まじめにm17n化しようと思ったら、まず$KCODEをm17n化しないといけなさそうな・・・^^;;<br>UTF-8に対応すればおっけ〜♪なら楽なのでしょうが。

_ shugo (2005-04-23 (Sat) 09:16)

実はすでにまつもとさんがブランチで一度作業されています。<br>1.7のころがベースなので、すぐにはマージできませんけど:(