関連テーブルのレコード数をjoin以外で取ってくる

あるテーブルの一覧を表示するときに、そのテーブルと関連づけられているデータが何個あるのか同時に表示したくなったんだが、これでちょっとはまった。

以下の条件での話

  • Rails1.2.6
  • Ruby1.8.6 P114

テーブル構造は以下の用になっている。

Table Table Table
Games Game2Makers Makers
id id,game_id,maker_id id

1件表示するときは:includeで引っ張ってきて特に問題がない。表示的にもスムースだし速度的にもいける。

 @game = Game.find(1,:include=>:makers)
 @maker = Maker.find(1,:include=>games)

ところが一覧で表示するときに、ついでに関連テーブル側の個数も出そうとしたらとたんにスピードが低下。

@makers = Maker.paginate(:page=>params[:page],
                         :order=>"makers.name",
                         :include=>:games,
                         :per_page=>50)  

Viewは以下の通り。最後のsizeのところで個数を出していた。本当に個数しか必要なくて、その中の情報は全くいらないんだが、そこが速度低下をまねている。

<%@makers.each do |maker| %>
<%=link_to(maker.name,:controller=>:maker,:action=>:show,:id=>maker.id)%>(<%=maker.games.size%>個)
<% end %>

少ししらべていたんだけどうまく回避できる方法が見あたらない(悲)。そこで、数が知りたいだけなら中間テーブルのレコード数を調べればいいので、そこの数を:joinで無理矢理数えることにした

@makers = Maker.paginate(:joins=>"inner join game2makers on makers.id = game2makers.maker_id",
                        :select=>"makers.id,makers.name,count(*)",
                        :group=>"makers.id,makers.name",
                        :page=>params[:page],
                        :order=>"makers.name",
                        :per_page=>50)                               

なんだか、すごーく生SQLを書いてるのと変わらないような気配が漂うんだけど、これでいいんだろうか。Viewは一応個数表示部分だけが変わるのでたいした変化じゃ確かにないのはないんだが。

<%@makers.each do |maker|%>
  <%=link_to(h(maker.name),:controller=>:maker,:action=>:show,:id=>maker.id)%>(<%=maker["count(*)"]%>個)
<%end%>

Rails2.0系だとこの辺は便利になってるのかなあ。