routes.rb内でリダイレクトの記述していたときに複数のformatを持つパスのリダイレクトに躓いたのでメモ代わりに。
内容
# jsonがデフォルトで、`/samples.xml`でアクセスされるとxmlで処理する
get :samples, to: 'sample#index', defaults: { format: :json }
という設定を
get :samples, to: redirect('new_samples', status: 301)
に置き換える。
この場合、/samplesに接続すると問題なく/new_samplesにリダイレクトされるが、
/samples.xmlに接続すると/new_samplesにリダイレクトしてしまいjsonで処理してしまいます。
対応したこと
二通りありました。
ブロック処理
Rails Routing from the Outside In #3.12 Redirectionを見るとredirectにはブロックを指定できるようなので、ブロック内で無理やり実現しました。
get :samples, to: redirect { |params|
"new_samples#{params[:format].present? ? ".#{params[:format] : ''}"
}, status: 301
どうも、よくある
get 'samples/:id', to: redirect('new_samples/%{id}', status: 301)
のような指定で
get :samples, to: redirect('new_samples.%{format}', status: 301)
みたいにしてみると/samples.xmlに接続した時はうまく/new_samples.xmlにリダイレクトするんですが、
/samplesに接続するとエラーになります。
かなり力技になっているのと、上記のようにパス内にidみたいなパラメータがある場合、%{id}の書き方が使えなくなってしまい、
get 'samples/:id', to: redirect { |params|
"new_samples/#{params[:id]}#{params[:format].present? ? ".#{params[:format] : ''}"
}, status: 301
というように書かないといけないです。
2つに分割
formatがある場合とない場合とで分ける方法です。
get 'samples', to: redirect('/new_samples', status: 301), format: false
get 'samples(.:format)', to: redirect('/new_samples.%{format}', status: 301), format: true, as: :samples_format
formatがある場合のリダイレクトのほうはasで別名をつけてあげないと〜〜_pathのメソッドが名無しになってしまいます。
最後に
いずれのパターンも力技な感じなので、もっとスマートな書き方ご存知でしたら教えて下さい。