woshidan's blog

そんなことよりコードにダイブ。

redirct_to :back で前のページへ戻ると、それに関連して。

redirct_to :back で前のページへ戻る

# in controller
redirect_to :back
# in view
link_to :back

で前のページに戻れる。
導線がたこ足みたいなページでとりあえず前のページに戻るボタンがあったら便利だな、とか。
(もしかしたらそれはそもそもの設計を考え直したり、パンくずリストとか別のことを考えた方がいいのかもしれない。
純粋に自分用のツールならブラウザバックを使う())

で、便利だと思って深く考えずに使っていたらコントローラのテストで詰んだ。 

エラーと対処法

(ActionController::RedirectBackError) "No HTTP_REFERER was set in the request to this action ...

refererという単語に聞き覚えがあったのだけど、よく分からず
(こういうことがよくある……)
http://stackoverflow.com/questions/771656/correctly-doing-redirect-to-back-in-ruby-on-rails-when-referrer-is-not-availabl
などを見たら、要するに前のページへ戻る、の前のページの情報がない、とのこと。

テストではいきなりそのアクションのurlを叩くという真似をしたので起きたみたい。
対処法としては、とりあえず発生したエラーを拾ってやって、例外処理の中で別のアドレスへリダイレクトさせる。

begin
  redirect_to :back
rescue ActionController::RedirectBackError
  redirect_to root
end

テストは無事とおるようになったけど、なんだか不安になったのでもう少し調べた。

ActionControllerとは

ActionControllerってTestUnitではcontrollerのテストのクラスのスーパークラスにそういう文字列があった気がする。

require 'test_helper'

class SampleControllerTest < ActionController::TestCase

だから、上のエラーを見たとき、もしやこれ、テストの環境でだけ発生するのか、
Railsの環境で発生するのか(そうだったら、そもそもテストに使えてないしそんなわけないだろうが)、
実際の環境に存在しないエラーの処理を本番環境のコードに埋め込むとかやだーとか。
要らない心配をした。

ActionController

によると(もっといろいろあったけど)、

の2つのクラスがあって、ActionController::TestCaseはActionController::Baseのテスト用のクラス。
同じようにレスポンスを返し、同じようにエラーを吐く(と思われる)。
ApplicationControllerはActionControllerを継承しているので、
ActionController::RedirectBackErrorに対応するって書いていても大丈夫。

関係ないけど、testunit系でテンプレートのテストってこんな感じなのか。

ActionController::TemplateAssertions

redirect_to :back で呼び出されるrefererはどの変数に入っているのか

例外処理書かなくても入ってなければセットすればいいじゃない、とも思った。

ActionController::Redirecting

redirect_to のオプションについて


:back - Back to the page that issued the request. Useful for forms that are triggered from multiple places. Short-hand for redirect_to(request.env["HTTP_REFERER"])

とあるので、request.env["HTTP_REFERER"]に入っているらしい。
アドレスして来たユーザのIPアドレスの取得などもrequest.envの要素路して含まれているみたい。
さて、これをstubさせて、とか思ったけど、前段の理由で、実環境でいきなりアドレスを叩いた場合にも起こりうるのだから止める。