Rescue_from ActionController:: RoutingError в Rails 4

У меня есть следующая ошибка:

ActionController::RoutingError (No route matches [GET] "/images/favicon.ico")

Я хочу показать страницу error404 для ссылок, которые не существуют.

Как я могу это достичь?

Ответы

Ответ 1

В application_controller.rb добавьте следующее:

  # You want to get exceptions in development, but not in production.
  unless Rails.application.config.consider_all_requests_local
    rescue_from ActionController::RoutingError, with: -> { render_404  }
  end

  def render_404
    respond_to do |format|
      format.html { render template: 'errors/not_found', status: 404 }
      format.all { render nothing: true, status: 404 }
    end
  end

Обычно я также спасаю следующие исключения, но это зависит от вас:

rescue_from ActionController::UnknownController, with: -> { render_404  }
rescue_from ActiveRecord::RecordNotFound,        with: -> { render_404  }

Создайте контроллер ошибок:

class ErrorsController < ApplicationController
  def error_404
    render 'errors/not_found'
  end
end

Затем в routes.rb

  unless Rails.application.config.consider_all_requests_local
    # having created corresponding controller and action
    get '*path', to: 'errors#error_404', via: :all
  end

И последнее, что нужно создать not_found.html.haml (или любой другой шаблонизатор, который вы используете) в /views/errors/:

  %span 404
  %br
  Page Not Found

Ответ 2

Копирование значка избранного в app/assets/images сработало для меня.

Ответ 3

@Andrey Deineko, ваше решение работает только для RoutingError, созданного вручную внутри conrtoller. Если я попробую с url my_app/not_existing_path, я все равно получаю стандартное сообщение об ошибке.

Я предполагаю, что это связано с тем, что приложение даже не доходит до контроллеров, так как Rails вызывает ошибку раньше.

трюк, который решил проблему для меня, заключался в том, чтобы добавить следующую строку на пути end:

Rails.application.routes.draw do
  # existing paths
  match '*path' => 'errors#error_404', via: :all
end

чтобы поймать все не предопределенные запросы.

Затем в ErrorsController вы можете использовать respond_to для обслуживания html, json... request:

class ErrorsController < ApplicationController
  def error_404
    @requested_path = request.path
    repond_to do |format|
      format.html
      format.json { render json: {routing_error: @requested_path} }
    end
  end
end