Rails 3.2 ошибка маршрутизации. Идентификатор ошибки конфликтует с другим идентификатором объекта - PullRequest
3 голосов
/ 21 марта 2012

Мы только что обновили наше приложение до Rails 3.2.2 и теперь имеем проблему с маршрутизацией для обработки ошибок.

За В блоге Хосе Валима мы добавили следующее:
config.exceptions_app = self.routes в config / application.rb
match "/404", :to => "errors#not_found" в config / rout.rb
(и соответствующий контроллер / просмотры).

Проблема в том, что нам нужно ourdomain.com/id, чтобы отобразить страницу индекса для категории продуктов id.

Итак, теперь ourdomain.com/404 показывает нашу страницу 404, когда она должна показать нашу страницу списка категорий для категории с id из 404.

Как мы можем обойти это?
Есть ли способ заставить приложение добавлять каждую ошибку с error_, прежде чем она будет оценена с помощью routes?
Или, может быть, как-то установить config.exceptions_app для ссылки на пространство имен в файле routes?
Или я могу создать второй набор маршрутов и установить config.exceptions_app = self.second_set_of_routes?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 20 сентября 2012

У нас была та же проблема - коды ошибок, конфликтующие с идентификаторами для ресурсов на корневом уровне (например, конфликты между ourdomain.com/:resource_id и ourdomain.com/404).

Мы изменили решение Хосе Валима, добавив ограничение маршрута, которое применяется только при обработке исключения:

# Are we handling an exception?
class ExceptionAppConstraint
  def self.matches?(request)
    request.env["action_dispatch.exception"].present?
  end
end

MyApp::Application.routes.draw do
  # These routes are only considered when there is an exception
  constraints(ExceptionAppConstraint) do
    match "/404", :to => "errors#not_found"
    match "/500", :to => "errors#internal_server_error"

    # Any other status code
    match '*a', :to => "errors#unknown"
  end
  ...
  # other routes, including 'match "/:resource_id"'
end

(Мы только что наткнулись на это решение прошлой ночью, поэтому у него не было большого времени выгорания. Мы используем Rails 3.2.8)

1 голос
/ 21 марта 2012

Есть одно решение, которое я нашел до сих пор:

# application_controller.rb

def rescue_404
  rescue_action_in_public CustomNotFoundError.new
end

def rescue_action_in_public(exception)
  case exception
    when CustomNotFoundError, ::ActionController::UnknownAction then
      #render_with_layout "shared/error404", 404, "standard"
      render template: "shared/error404", layout: "standard", status: "404"
    else
      @message = exception
      render template: "shared/error", layout: "standard", status: "500"
  end
end

def local_request?
  return false
end

rescue_action_in_public - это метод, который Rails вызывает для обработки большинства ошибок.
local_request? метод говорит Rails прекратить сосатьесли это локальный запрос

# config/routes.rb
match '*path', controller: 'application', action: 'rescue_404' \
  unless ::ActionController::Base.consider_all_requests_local

Он просто говорит, что не может найти какой-либо другой маршрут для обработки запроса (например, *path), он должен вызвать действие rescue_404 на контроллере приложения (первый способ выше).

РЕДАКТИРОВАТЬ

Эта версия работала для меня хорошо!Попробуйте добавить к application.rb

# 404 catch all route
config.after_initialize do |app|
  app.routes.append{ match '*a', to: 'application#render_not_found' } \
    unless config.consider_all_requests_local
end

См .: https://github.com/rails/rails/issues/671#issuecomment-1780159

1 голос
/ 21 марта 2012

Кажется, что этот маршрут жестко запрограммирован в методе show_exceptions ( см. Источник )

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

env["PATH_INFO"] = "/error_#{status}"

(что, разумеется, не имеет никакого решения вообще).

Не мешало бы спросить: если вы подумали, что было бы хорошоваш собственный контроллер ошибок реализован так просто и отчаянно хотите его иметь, что не было бы даже более «RESTful», если бы ваш маршрут был yourdomain.com/product/:id?

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