Railsでページング位置を覚えておく方法
RailsでScaffoldの作ったコントローラーに WillPaginate等で一覧のページングを追加したアプリを作る事がよくあると思いますが、ページングで2ページ目を表示し、そこで編集し戻ってくると一覧は1ページ目に戻ってしまいます。
編集しても2ページ目に戻ってこれるようにするのに、皆さんはどうしていますか?
class TodosController < ApplicationController def index @todos = Todo.find(:all, :order => :due) end def show @todo = Todo.find(params[:id]) end def edit @todo = Todo.find(params[:id]) end def update @todo = Todo.find(params[:id]) if @todo.update_attributes(params[:todo]) flash[:notice] = 'Todo was successfully updated.' redirect_to(@todo) else render :action => "edit" end end ....
一覧表示のページ位置を覚え、表示/編集後に一覧のページに戻る方法には大きく
- パラメター、hidden等でページ位置を表示/編集処理で持ち回る
- ページ位置をセッションに覚えておき、一覧表示に戻った際にセッション中のページ位置を使う
などがあると思います。
1の方法は結構面倒ですし、表示/編集処理が本質的でなページ位置などの処理をするのは良くないと思います。
2の方法は簡単に実装できるのですが、セッションを無効にするタイミングの考慮、コントローラが複数ある場合のセッションを分けたりする必要があります。
今、作っているアプリでは 2の方式なのですが、Railsのflashを組み合わせてみました。flashは次のページでの表示まで有効なセッションなので、自動的に消えてくれるのが良い点です。
下のコードの様に、一覧に戻る際にページ位置をflashを使って渡すのがポイントです。一覧の表示後はflashは消えてしまうので、他のコントロラーや他のアクションに行って戻ってきた場合は、記憶したページ位置は使われません。
class TodosController < ApplicationController def index @todos = Todo.paginate(:page => flash[:page] ? flash[:page] : params[:page], :order => :due, :per_page => 5) session[:last_page] = @todos.current_page end def show @todo = Todo.find(params[:id]) flash[:page] = session[:last_page] end def edit @todo = Todo.find(params[:id]) flash[:page] = session[:last_page] end def update @todo = Todo.find(params[:id]) if @todo.update_attributes(params[:todo]) flash[:notice] = 'Todo was successfully updated.' redirect_to(@todo) else render :action => "edit" end end ....
もちろん、URLを手入力して、表示等を行うと一覧の意図しないページに戻る可能性もありますが・・・