redirect_to とフラグメント修飾子と実体参照

前振り

フラグメント修飾子とは、今回の話の範囲では
http://api.rubyonrails.org/classes/ActionDispatch/Http/URL.html#method-c-url_for
というアドレスに含まれる「#」以降、つまり「method-c-url_for」の部分になります。

そして Safari を使ってリダイレクトを行うと、このフラグメント修飾子が消えるというのが今回発生した問題でした。

http ヘッダにおけるフラグメント修飾子の扱い

RFC にきちんと定義されています。
ftp://ftp.rfc-editor.org/in-notes/rfc2396.txt

非常に長いのですが、結論から言うとヘッダにフラグメント修飾子をつける事はできない、との事。

Rails における解決方法

Rails においては redirect_to を使う際に :anchor オプションをつける事で解決できます。

redirect_to hoge_path(anchor: 'fuga')

問題の解決だけを行いたいならここまでで完了となります。以下は動作が気になって仕方ない人向け。

どうやってそれをやったのか

前提でヘッダにフラグメント修飾子は含まないと述べたのに何故 Rails は実装できているのか、気になったので調べてみました。
最終的にたどり着いたのが

actionpack/lib/action_dispatch/journey/router/utils.rb

このファイル。記事執筆時に見つかった github 上のリンクも添付しておきます。

https://github.com/rails/rails/blob/08754f12e65a9ec79633a605e986d0f1ffa4b251/actionpack/lib/action_dispatch/journey/router/utils.rb

使われているのは escape_fragment というメソッドなのですが、文字列のエスケープを行い「#」を「%23」に変換していました。