在 Rails 3 中捕获自定义 404 的未知操作

发布于 2024-12-03 12:02:28 字数 936 浏览 1 评论 0原文

我想捕获 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):

也尝试过 save_from ActionController::UnknownAction

有什么建议吗? 谢谢!

I want to catch unknown action error in Rails 3, that shows "Unknown Action" error on development and the 404.html on production. I tried putting this rescue_from handler on my ApplicationController (and also on an actual controller, just in case) but I still see the ugly error.

I have custom stuff on the 404, and it can't be plain .html file.

My route:

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

The URL I'm accessing: /user/elado/xxx

The rescue_from code:

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

def action_not_found
  render text: "action_not_found"
end

The error in the browser:

Unknown action

The action 'xxx' could not be found for UsersController

And in the console:

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):

Tried also rescue_from ActionController::UnknownAction.

Any suggestions?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

热血少△年 2024-12-10 12:02:28

当 Rails 3 发布时,rescue_from 略有问题(在 3.1 中也仍然有问题)。基本上你不能:

rescue_from ActionController::RoutingError

不再了。请参阅此处

目前的解决方案是 Hamilton 推荐的。使用通向“路由错误”路由的全部路由。确保将其放在 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 等引擎,则 catch all 路由将使 Rails 忽略引擎的路由。

如果您没有使用有自己的路线的引擎,那么您应该没问题。
但是,如果您确实使用定义自己的路由的引擎,请参阅@arikfr 的答案。

rescue_from was slightly broken when Rails 3 came out (still broken in 3.1 too). Basically you can't:

rescue_from ActionController::RoutingError

anymore. See here.

The solution, for now, is what hamiltop recommends. Use a catch all route that goes to your "routing error" route. Make sure you put it at the end of your config\routes.rb file so it is processed last.

# 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

Note: This method has one major drawback. If you use an engine such as Jammit or Devise the catch all will route will make Rails ignore the engine's routes.

If you aren't using an engine that has it's own routes then you should be fine.
However, if you do use an engine that defines its own routes see @arikfr's answer.

尝蛊 2024-12-10 12:02:28

使用捕获所有路由来处理 404 错误(如 @Seth Jackson 建议的那样)有一个主要缺点:如果您使用任何定义自己的路由的 Rails 引擎(例如 Jammit),它们的路由将被忽略。

更好、更合规的解决方案是使用能够捕获 404 错误的 Rack 中间件。在我的一个项目中,我实现了这样的 Rack 中间件,将这些错误报告给 Hoptoad。我的实现基于此:https://github.com/vidibus/vidibus-routing_error,但是再次调用我的 Rails 应用程序来处理 404 错误,我在 Rack 中间件中执行此操作,并让 nginx 显示 404 页面。

Using a catch all route to handle 404 erros (as @Seth Jackson suggested) has one major drawback: if you use any Rails engines that define their own routes (such as Jammit) their routes will be ignored.

Better and more compliant solution would be to use a Rack middleware that will catch 404 errors. In one of my projects, I've implemented such Rack middleware that reports these errors to Hoptoad. I've based my implementation on this one: https://github.com/vidibus/vidibus-routing_error, but instead of invoking my Rails app again to handle the 404 error, I do it in the Rack middleware and let nginx to show the 404 page.

狂之美人 2024-12-10 12:02:28

如果你真的想拯救控制器中的 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

这会覆盖 AbstractController::Baseprocess 方法code> 引发 AbstractController::ActionNotFound (参见 来源)。

If you really want to rescue AbstractController::ActionNotFound in a controller, you can try something like this:

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

This overrides the process method of AbstractController::Base that raises AbstractController::ActionNotFound (see source).

山色无中 2024-12-10 12:02:28

您尝试过catch all 路线吗?

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

您当前使用的通配符路线是一个坏主意。

我建议定义您关心的路由,然后将其作为routes.rb 的最后一行(首先在routes.rb 中定义的路由胜过后面的定义)。然后您可以呈现您想要的任何页面(并指定 404 状态代码)。

编辑:如果你真的想使用当前的方法...(尽管这看起来可能会被弃用)

def rescue_action(exception)
例外情况
当 ActionNotFound 时,UnknownAction 然后
# 在这里处理这些异常
别的
极好的
结尾
结尾

Have you tried a catch all route?

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

The wildcard route that you are current using is a Bad Idea(tm).

I would recommend defining the routes you care about, and then doing a catchall as the last line of routes.rb (routes defined first in routes.rb trump later definitions). Then you can render whatever page you want (and specify the 404 status code).

Edit: If you really want to use your current approach... (although this seems like it could be deprecated)

def rescue_action(exception)
case exception
when ActionNotFound, UnknownAction then
# Handle these exceptions here
else
super
end
end

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文