ワイルドカードセグメントを使ってNo route matchesに対応する


環境

ruby 2.5.1
Rails 5.0.6

方法

どこにも一致しないURLにアクセスされた場合、ApplicationController#render404を呼び出すことで、404ページをrenderします。

ルーティングの設定

ワイルドカードセグメントを用いることで、あらゆるルーティングを拾うことができます。

config/routes.rb
MyApp::Application.routes.draw do

  ...

  get '*unmatched_route' => 'application#render404'
end

例えば上記のルーティングだと、/hoge/fugaにアクセスした場合のパラメータは以下のようになります。

Started GET "/hoge/fuga" for ::1 at 2018-07-30 08:04:12 +0900
Processing by ApplicationController#render404 as HTML
  Parameters: {"unmatched_route"=>"hoge/fuga"}

参考

render404の設定

protect_from_forgeryを設定しているので少し注意が必要です。
jsフォーマットの場合はそのままtext/javascriptとしてrenderしてしまうとInvalidCrossOriginRequestと怒られてしまうので、以下のようにrender404exceptしてやるか、

protect_from_forgery with: :exception, except: :render404

jsフォーマットのときだけrenderする内容を変更してあげればOKです

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception

  ...

  def render_404
    respond_to do |format|
      format.html { render "path/to/error_page", layout: "errors", status: 404 }
      format.js { render json: '', status: :not_found, content_type: 'application/json' }
      format.any { head :not_found }
    end
  end

  ...

end

参考

以上です