2009年9月30日水曜日

[Ruby on Rails]will_paginateで集計関数を使う場合の注意

will_paginateはページングを行うのに非常に便利なruby on railsのプラグインですが、ちょっと意図しない挙動があったのでご報告。

順番に追っていきます。

一番ベーシックな書法

@posts = Post.paginate({
:page => params[:page],
:order => 'created_at DESC'
})


条件をつけてみる
@posts = Post.paginate({
:conditions => ["posts.id = ?", params[:id]],
:page => params[:page],
:order => 'created_at DESC'
})


取得するカラムを指定してみる
@posts = Post.paginate({
:select => "posts.id, posts.title, posts.created_at",
:conditions => ["posts.id = ?", params[:id]],
:page => params[:page],
:order => 'created_at DESC'
})


データベース(MySQL)の集計関数(COUNT)を使ってみる
ここでひっかかった
@posts = Post.paginate({
:select => "COUNT(comments.id) as cnt, posts.id, posts.title, posts.created_at",
:joins => "LEFT JOIN comments ON posts.id = comments.post_id",
:conditions => ["posts.id = ?", params[:id]],
:group => "posts.id, posts.title, posts.created_at",
:page => params[:page],
:order => 'created_at DESC'
})

※ 全体の件数を返すクエリがなんかおかしい
SELECT
count(*) AS count_all,
posts.id,
posts.title,
posts.created_at
FROM
posts
LEFT JOIN comments ON posts.id = comments.post_id
WHERE
posts.id = '9999'
GROUP BY
posts.id,
posts.title,
posts.created_at

どう見ても全体の件数を返すクエリにはなっていません。
どうも、select やら joins やら group やらを指定するとうまく処理してくれない模様です。

それでいて全体件数 (@posts.total_entries) はちゃんとした値が入ってたりするので分かりにくいです。



これは自分で全体の件数を指定するしかないようですが、ちょっと書き直すだけで対応できるようなので一安心。

http://gitrdoc.com/mislav/will_paginate/tree/master/
@entries = WillPaginate::Collection.create(1, 10) do |pager|
result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset)
# inject the result array into the paginated collection:
pager.replace(result)

unless pager.total_entries
# the pager didn't manage to guess the total count, do it manually
pager.total_entries = Post.count
end
end

createメソッドの第3引数には全体の件数(total)を指定できるので、ここに自分で集計した件数を指定してやればいいわけです。


以上をふまえて書き換えたのがこちら

[改良版] データベース(MySQL)の集計関数(COUNT)を使ってみる

total = Post.count({:conditions => ["posts.id = ?", params[:id]]})

@posts = WillPaginate::Collection.create((params[:page] || 1), 10, total) do |pager|
result = Post.find(:all, {
:select => "COUNT(comments.id) as cnt, posts.id, posts.title, posts.created_at",
:joins => "LEFT JOIN comments ON posts.id = comments.post_id",
:conditions => ["posts.id = ?", params[:id]],
:group => "posts.id, posts.title, posts.created_at",
:limit => pager.per_page,
:offset => pager.offset
})
pager.replace(result)
end




[関連記事]
ActiveRecord以外でwill_paginateを使う方法
will_paginateの便利なViewヘルパー

2009年9月23日水曜日

最近気になったjQueryプラグイン7選

実用性の高いものから実験的なものまで


jquery.path

曲線&多次元のアニメーションを実行できるプラグイン
http://github.com/weepy/jquery.path


jquery.trace.js

jQueryのセレクタの挙動を確認できるプラグイン。
下記サイトにはFirebugを利用したデモビデオがあります。
http://www.bennadel.com/blog/1710-jQuery-Plugin-Tracing-Your-Selector-Paths.htm


CSS Exchanger

CSSを丸ごと動的に変更できるプラグイン。
http://tympanus.net/codrops/2009/09/09/switching-styles-jquery-css-exchanger/


jQuery Image Overlay Plugin

オーバーレイで画像にタイトルやキャプションをつけられるプラグイン
http://www.ferretarmy.com/files/jQuery/ImageOverlay/ImageOverlay.html


jQuery (mb)Gallery

ものすごく凝った感じの画像ギャラリー用プラグイン
http://pupunzi.wordpress.com/2009/02/28/mbgallery/


jQuery maxImage plugin

画像の大きさをちょうどいい感じに自動でリサイズしてくれるプラグイン。
http://www.aaronvanderzwan.com/maximage/


history plugin
Ajaxばりばりのページでもブラウザの「戻る」ボタンや「ブックマーク」を効かせられるプラグイン。
http://www.mikage.to/jquery/jquery_history.html

2009年9月20日日曜日

2ちゃんねるまとめのまとめ - 2ちゃんのまとめブログをまとめたサイト

前々から作ろう作ろうと思いつつ先延ばしになってたものの何とか形になったのでご報告します。

2ちゃんねるまとめのまとめ
http://2chfeed.appspot.com


1年くらい前にGoogle Gadgetsの勉強として作成した「2ちゃんねるまとめのまとめ」ですが、Google Analyticsによると3万人以上の方が利用してくれているようです (ありがとうございます!)。

これはそのWebサイト版という位置づけです。


Webサイト版の特長は...
実は、ガジェット版とそんなに変わってません(!!)
しいて言えば、まとめブログさんの数を 20 に増やしたくらいでしょうか。


とはいえ、ガジェットでは実現できなかった機能をいろいろ妄想しています。

これから追加したい機能

・ しおり (ここまで読んだ)
・ Twitterのbot
・ ランキング


とりあえずはRSSリーダー代わりに使っていただければと思います。
こんなことやって欲しいということがあれば是非是非コメントしてください。
よろしくお願いします。

2009年9月2日水曜日

Twitterのつぶやきを表示するmixiアプリを作ってみました

正式公開前にはなんかしらのアプリを作ろうと思っていましたがいつのまにか正式公開していました。

遅れちゃなんめえってことで
とりあえずお勉強という目的で、Twitterのつぶやきを表示するアプリを作ってみました。

Twitter@mixi: mixiアプリ
http://mixi.jp/view_appli.pl?id=7254

説明することはほんとんどありません。
本当にただtweetsを表示するだけですので…


自分の中では

jQueryプラグイン => Google Gadgets => OpenSocialアプリ (mixiアプリ)

という流れで、プラットフォームに合わせて再生産した感じです。

OpenSocialアプリはGoogle Gadgetsを作ったことがある人には馴染みやすいですね。
XMLのフォーマットが同じですし。
gadgets APIも共通です。

opensocial APIもgadgets APIと書式が似ているのでとっつきやすいのですが、
mixi Platformだとサポートされていないものがちらほらあります。

あれ、opensocialの仕様どおりなのに思った通りに動かないぞ!?
という時は下のサイトを舐めるように確認する必要があるかと。面倒ですが。

mixi Developer Center
http://developer.mixi.co.jp/appli