Sinatra - 为什么404错误块永远不会触发?

时间:2014-07-24 02:43:44

标签: ruby exception-handling error-handling sinatra

这是一个简单的应用程序:

class App < Sinatra::Base
    set :show_exceptions, false

    not_found do
       slim :err_404
    end

    post "/doit" do
        user ||= User.find(params["userid"]) || halt(404)
    end
end

当给出无效的用户ID时,404错误块应该触发然后呈现404页面。相反,Sinatra在页面上显示“Internal Server Error”,并且此堆栈跟踪将打印到控制台:

Problem:
  Document(s) not found for class User with id(s) 53d06a8ca7b7d52d11300003.
Summary:
       ....

我猜测halt(404)没有被调用。我正在关注这个blog post about error handling,那为什么同样的事情不会在这里发挥作用呢?

1 个答案:

答案 0 :(得分:2)

假设您正在使用ActiveRecord,如果没有匹配的记录,User.find(params["userid"])将引发ActiveRecord::RecordNotFound异常。在404处理程序运行并结束路由处理之前抛出此异常,从而导致内部服务器错误。

要修复它,你可以检查异常,如果它被引发则调用404处理程序:

post "/doit" do
  begin
    user ||= User.find(params["userid"]
  rescue ActiveRecord::RecordNotFound
    halt(404)
  end
end

更好的解决方案可能是使用find_by_id代替,这可以避免使用流控制的异常:

post "/doit" do
    user ||= User.find_by_id(params["userid"]) || halt(404)
end