Browse Month: January 2011

will_paginate tips

Rails で、ページングをいれるとき will_paginate が便利です。will_paginate は、ページングの際、page というリクエストパラメータでページング処理をしますが、このパラメータが空や数字でない文字が入ってしまったとき、「WillPaginate::InvalidPage」 という例外が発生します。

本番環境では、例外が発生したとき、例外の詳細をメールで送信するようにしているのですが、このエラーが何度が頻発して対策を講じるにしました。

まず、考えたのは will_paginate 側本体を変更して、例外を閉じ込めてしまうことでした。will_paginate の過去のチケットをみていると、まったく同じチケットがあって結論的に無効なチケットとなっています。その内容では、Rails2 だと 404 になるとありましたが、僕の環境では例外として表示されていました。

どうやら、僕の環境では ApplicationController 内で、rescue_action を定義しているため、例外として表示されてしまったようです。

また、will_paginate でも、ページ番号がおかしいときの挙動がちゃんと考えられて、Rails2 から追加された rescue_responses を使うことで 404 にするのか、あるいは特定のページにするのか挙動が決められるようになっています。

Exception: WillPaginate::InvalidPage

ActionController::Base.rescue_responses['WillPaginate::InvalidPage'] =
:not_found

rescue_action を定義している場合、上の仕組みではうまくいかないので、自前のrescue_action を次のように変更しました。


def rescue_action(exception)
if RAILS_ENV == 'production'
case exception
when ActionController::RoutingError,
ActionController::InvalidAuthenticityToken,
WillPaginate::InvalidPage
# Do not send error email
render :partial => '/system/notfound', :layout => true, :status => 404 and return
else
begin
UserMailer.deliver_email_snapshot(exception,
clean_backtrace(exception),
session.instance_variable_get("@data"),
params,
request.env)
rescue => e
logger.error(e)
end
end
render :partial => '/system/error', :layout => true, :status => 500
else
super
end
end

本番環境のときにみ、特定の例外が発生したときはメールを送らず 404 ページ、それ以外の例外のときはメールを送信してから 500 ページを表示するようになっています。

この仕組みなら、発生してもよい許容する例外をフィルターしつつ、それ以外の例外が発生したときはメールを送信して対策できるため、便利ですね。
あとは、テスト環境がほとんど整っていないので、ちゃんと整備して、品質を上げていきたいところです。

2011年もよろしくお願いします

ついに2011年になりました。

今年も、自分のインフラまわりで経験したことやさまざまな情報を、このブログから発信していければと思います。

2011年もよろしくお願いいたします!