RailsでURLの末尾にスラッシュ(trailing_slash)をつける方法

SEO要件のためにURLの末尾に/(スラッシュ)をつけることがあります。静的ファイルや少ないページ数のサイトであれば愚直にスラッシュつける設定をやっていけばよさげですが、Railsのようなフレームワークで実現するにはどうしたらよいでしょうか。機会があったのでやってみました。

trailing_slash: を使う

# routes.rb

Rails.application.routes.draw do
  get '/items/:id', to: 'items#show', trailing_slash: true, as: 'item_detail'
end

とすると、 item_detail_pathをクリックした先のURLがしっかりとhttp:example.com/items/22/といった感じで末尾にスラッシュが付加されるようになります。 ちなみに上記は各ルーティングへの個別設定なのですが、アプリケーション全体で、末尾スラッシュ(これをtrailing_slashという)をつけたい場合は

# config/application.rb
class Application < Rails::Application
    config.action_controller.default_url_options = { :trailing_slash => true }
end

とすると、アプリケーションで発行するURL全体にtrailing_slashが付加される。

ルーティングオプションのtrailing_slashで賄えないこと

それは、直接URLを叩きにいった場合、末尾スラッシュ追加処理が行なわれないということ。

# routes.rb

Rails.application.routes.draw do
  get '/items/:id', to: 'items#show', trailing_slash: true, as: 'item_detail'
end

と設定した上で、例えばhttp://example.com/items/45を叩くとhttp://example.com/items/45のままです。http://example.com/items/45/とはなりません。カノニカルでtrailing_slashされたURLをセットしていても検索エンジンによっては処理が変わりうるので、せっかくSEO対策のためにtrailing_slashしたにもかかわらず不安が残ります。

結論:末尾スラッシュがなければ、末尾スラッシュ付きのURLリダイレクトさせればよい

先にコードを載せておきます。

# ApplicationController
def trailing_slash
    redirect_to "#{request.original_url}/" unless request.original_url.match(/\/$/)
end
# ItemsController
class ItemsController < ApplicationController
    before_filter :trailing_slash, only: [:show]
...
end

routes.rbの中で完結させるのは難しいので、コントローラ層で処理を書いてあげる。ApplicationControllerを読み込むタイミングでもしURLの末尾にスラッシュがないのであれば、スラッシュ付きにURLを変えてリダイレクトさせるとよい。これでroutes.rbを汚さずとも末尾スラッシュ追加ができるようになる。また、SEO要件としては追加したいアクション(path)が決まっている場合もありますね。そのときは上記コード例のようにbefore_filterで末尾スラッシュを付加させたいアクションを指定してあげるとよいです。