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
のメソッドが名無しになってしまいます。
最後に
いずれのパターンも力技な感じなので、もっとスマートな書き方ご存知でしたら教えて下さい。