在Ruby / Sinatra中,如何使用ERB模板和错误消息暂停
在我的Sinatra项目中,我希望能够同时停止错误代码和错误消息:
halt 403,"Message!" 反过来,我想要在错误页面模板中呈现(使用ERB).例如: error 403 do erb :"errors/error",:locals => {:message => env['sinatra.error'].message} end 然而,显然env [‘sinatra.error’].message(又名自述文件和每个网站都说我应该这样做)并不会暴露我提供的信息. (此代码在运行时返回nil的未定义方法`message’:NilClass错误.) 我已经搜索了4-5个小时并尝试了所有内容,但我无法弄清楚消息通过ERB呈现给我的位置!有谁知道它在哪里? (看起来我能想到的唯一选择是写这个而不是上面的停止代码,每次我想停止: halt 403,erb(:"errors/error",:locals => {m: "Message!"}) 这段代码有效.但这是一个混乱的解决方案,因为它涉及硬编码错误ERB文件的位置.) (如果你想知道,这个问题与show_exceptions配置标志无关,因为set:show_exceptions,false和set:show_exceptions,:after_handler没有区别.) 解决方法
为什么不起作用 – 使用源代码!
让我们看看Sinatra源代码,看看为什么这个问题不起作用.主要的Sinatra文件( 所有停止的是: def halt(*response) response = response.first if response.length == 1 throw :halt,response end 例外情况包括: # Dispatch a request with error handling. def dispatch! invoke do static! if settings.static? && (request.get? || request.head?) filter! :before route! end rescue ::Exception => boom invoke { handle_exception!(boom) } [..] end def handle_exception!(boom) @env['sinatra.error'] = boom [..] end 但由于某种原因,这段代码永远不会运行(通过基本的“printf-debugging”测试).这是因为在调用块时运行如下: # Run the block with 'throw :halt' support and apply result to the response. def invoke res = catch(:halt) { yield } res = [res] if Fixnum === res or String === res if Array === res and Fixnum === res.first res = res.dup status(res.shift) body(res.pop) headers(*res) elsif res.respond_to? :each body res end nil # avoid double setting the same response tuple twice end 注意这里的catch(:halt). if Array === res和Fixnum === res.first部分是停止设置以及响应主体和状态代码的设置方式. 错误403 {..}块在调用中运行!: invoke { error_block!(response.status) } unless @env['sinatra.error'] 所以现在我们明白为什么这不起作用,我们可以寻找解决方案;-) 那么我可以用某种方式停止吗? 不是我能看到的.如果你看一下invoke方法的主体,你会发现在使用halt时总是设置了body.您不希望这样,因为您想要覆盖响应正文. 解 使用“真实”异常而不是暂停“伪异常”. Sinatra似乎没有预先定义的异常,但是handle_exception!确实查看http_status以设置正确的HTTP状态: if boom.respond_to? :http_status status(boom.http_status) elsif settings.use_code? and boom.respond_to? :code and boom.code.between? 400,599 status(boom.code) else status(500) end 所以你可以使用这样的东西: require 'sinatra' class PermissionDenied < StandardError def http_status; 403 end end get '/error' do #halt 403,'My special message to you!' raise PermissionDenied,'My special message to you!' end error 403 do 'Error message -> ' + @env['sinatra.error'].message end 哪个按预期工作(输出是错误消息 – >我的特殊消息给你!).您可以在此处返回ERB模板. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |