Подтвердить что ты не робот

Catch Неизвестное действие в Rails 3 для пользовательских 404

Я хочу поймать неизвестную ошибку действия в 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.

Любые предложения? Спасибо!

4b9b3361

Ответ 1

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

rescue_from ActionController::RoutingError

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

Решение, на данный момент, рекомендует хамильтоп. Используйте ловушку для всех маршрутов, идущих на ваш маршрут маршрутизации. Убедитесь, что вы положили его в конец вашего файла config\routes.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.

Ответ 2

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

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

Ответ 3

Если вы действительно хотите спасти 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 (см. источник).

Ответ 4

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

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

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

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

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

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