Поймать неизвестное действие в Rails 3 для пользовательских 404 - PullRequest
12 голосов
/ 08 сентября 2011

Я хочу отловить неизвестную ошибку действия в Rails 3, которая показывает ошибку «Неизвестное действие» при разработке и 404.html при производстве. Я попытался поместить этот обработчик rescue_from в мой ApplicationController (а также на настоящий контроллер, на всякий случай), но все равно вижу ужасную ошибку.

У меня есть пользовательский материал на 404, и он не может быть простым .html файлом.

Мой маршрут:

match '/user/:id/:action', controller: 'users'

URL, к которому я обращаюсь: /user/elado/xxx

Код rescue_from:

rescue_from AbstractController::ActionNotFound, :with => :action_not_found

def action_not_found
  render text: "action_not_found"
end

Ошибка в браузере:

Unknown action

The action 'xxx' could not be found for UsersController

А в консоли:

Started GET "/user/elado/xxx" for 127.0.0.1 at 2011-09-07 19:16:27 -0700

AbstractController::ActionNotFound (The action 'xxx' could not be found for UsersController):

Пробовал также rescue_from ActionController::UnknownAction.

Есть предложения? Спасибо!

Ответы [ 4 ]

14 голосов
/ 08 сентября 2011

rescue_from был немного сломан, когда вышел Rails 3 (все еще сломан в 3.1 тоже).В основном вы не можете:

rescue_from ActionController::RoutingError

больше.См. здесь .

На данный момент решение - это то, что рекомендует Hamiltop.Используйте перехват всех маршрутов, которые идут к вашему маршруту "ошибки маршрутизации"Обязательно поместите его в конец файла config \ rout.rb, чтобы он обрабатывался последним.

# Any routes that aren't defined above here go to the 404
match "*a", :to => "application#routing_error"

def routing_error
    render "404", :status => 404
end

Примечание: Этот метод имеет один существенный недостаток.Если вы используете такой движок, как Jammit или Devise, то поймать все, что будет направлено, заставит Rails игнорировать маршруты движка.

Если вы не используете движок с собственными маршрутами, тогда у вас все будет хорошо.Однако, если вы используете движок, который определяет свои собственные маршруты, смотрите ответ @ arikfr.

9 голосов
/ 08 сентября 2011

Использование перехвата всех маршрутов для обработки ошибок 404 (как предложил @Seth Jackson) имеет один существенный недостаток: если вы используете движки Rails, которые определяют свои собственные маршруты (например, Jammit), их маршруты будут игнорироваться.

Лучшим и более совместимым решением было бы использование промежуточного программного обеспечения Rack, которое будет отлавливать 404 ошибки.В одном из моих проектов я реализовал такое промежуточное программное обеспечение Rack, которое сообщает об этих ошибках в Hoptoad.Я основал свою реализацию на этом: https://github.com/vidibus/vidibus-routing_error,, но вместо того, чтобы снова вызывать мое приложение Rails для обработки ошибки 404, я делаю это в промежуточном программном обеспечении Rack и позволяю nginx показать страницу 404.

2 голосов
/ 01 апреля 2015

Если вы действительно хотите спасти AbstractController::ActionNotFound в контроллере, вы можете попробовать что-то вроде этого:

class UsersController < ApplicationController

  private

  def process(action, *args)
    super
  rescue AbstractController::ActionNotFound
    respond_to do |format|
      format.html { render :404, status: :not_found }
      format.all { render nothing: true, status: :not_found }
    end
  end


  public

  # actions must not be private

end

Это переопределяет process метод AbstractController::Base, который вызывает AbstractController::ActionNotFound (см. источник ).

0 голосов
/ 08 сентября 2011

Вы пробовали перехватить весь маршрут?

http://railscasts.com/episodes/46-catch-all-route

Используемый в настоящее время подстановочный знак является плохой идеей (tm).

Я бы хотелрекомендуем определить маршруты, которые вас интересуют, а затем выполнить перехват в качестве последней строки в файле rout.rb (маршруты, определенные первыми в маршрутах.Затем вы можете отобразить любую страницу по своему усмотрению (и указать код состояния 404.)

Редактировать: Если вы действительно хотите использовать свой текущий подход ... (хотя это кажется устаревшим)

def rescue_action (исключение): исключение случая, когда ActionNotFound, UnknownAction затем # Обрабатывают эти исключения здесь, иначе супер конец end

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...