アトラシエの開発ブログ

株式会社アトラシエのブログです

railsで煩雑なリダイレクトの管理

ウェブサービスを運用していると設計の変更や記事・ページの削除が頻繁にあります。

例えば今まで:author_name/articles/:idというURLで提供していたページがあったとして、これをシンプルにarticles/:idで提供するとします。

このとき何も考えずにURLを変更すると、もともとのURLに付与されていた検索エンジンからの評価が引き継がれません。

このような設計変更からくるURLの変化は301転送をかけてあげる必要があります。

これをrailsで実現するとこうなります。

 get ':author_name/articles/:id' => redirect("/articles/:id")

何も指定しないと301転送になります。

ところで改修によるリダイレクトならともかく、categories/break-fastcategories/breakfastにするとか、非常に細かいことでURLを変更したいと思うとconfig/routes.rbに毎回書いていくのはかなりだるいです。

そこで今回Railsで簡単にリダイレクトを管理する方法を紹介します。

Redirectionモデルを作る

オススメはRedirectionというモデルを作り、転送前URL(before), 転送後URL(after)を管理画面などから入稿できるようにすることです。

Routing

これであとはconfig/routes.rbの先頭にこのように書きます。

Rails.application.routes.draw do
  Redirection.all.each do |redirection|
    get "#{redirection.before}" => redirect("#{redirection.after}"), as: nil
  end
   ....
end

before, afterにはワイルドカードも使えるので、URLを正規化するような転送も可能です。

注意点

例えばarticles/1を削除したときにarticlesに転送したいとき(これを404にすべきかいなかは置いておきます), リダイレクトより先にarticles/:idにマッチングすると転送できません。したがって転送コードはルーティングの先頭に書きます。

あとはリダイレクトのレコード数が多すぎるとルーティングの処理に時間がかかるのですが、今のところ30,40程度では問題なさそうです。(仮に問題があれば古いリダイレクトは削除すればよいでしょう)

ただしルーティングは起動時に一度展開されてあとはキャッシュされるので管理画面からRedirectionモデルを追加してもサーバの再起動が必要です。

その他

この方法の問題はアプリケーション側で転送を行うのでAPサーバに処理が集中してしまう点でしょう。現在運用しているサービスがあまりスペック的に問題がないのでできていますが、そうでない場合はapacheで正規表現のリダイレクトを地道にするしかないのかも・・・。