我有一些代码需要在ruby中拯救多种类型的异常:
begin
a = rand
if a > 0.5
raise FooException
else
raise BarException
end
rescue FooException, BarException
puts "rescued!"
end
Run Code Online (Sandbox Code Playgroud)
我想做的是以某种方式存储我想要在某处救援的异常类型列表,并将这些类型传递给rescue子句:
EXCEPTIONS = [FooException, BarException]
Run Code Online (Sandbox Code Playgroud)
然后:
rescue EXCEPTIONS
Run Code Online (Sandbox Code Playgroud)
这是否可能,并且可能没有一些真正的黑客调用eval?鉴于我在TypeError: class or module required for rescue clause尝试上述内容时所看到的情况,我并不抱希望.
我在rails应用程序中使用sidekiq.默认情况下,任何人都可以通过在网址后附加"/ sidekiq"来访问Sidekiq.我想密码保护/验证sidekiq部分.我怎样才能做到这一点?
我正在试图找出如何解决eval()在Ruby 1.8.6中使用代码时出现的语法错误.
我希望以下Ruby代码:
#!/usr/bin/ruby
good_str = "(1+1)"
bad_str = "(1+1" # syntax error: missing closing paren
begin
puts eval(good_str)
puts eval(bad_str)
rescue => exc
puts "RESCUED!"
end
Run Code Online (Sandbox Code Playgroud)
运行时产生以下结果:
2
RESCUED!
Run Code Online (Sandbox Code Playgroud)
相反,我得到的是:
2
eval_rescue.rb:8: (eval):1: compile error (SyntaxError)
(eval):1: syntax error, unexpected $end, expecting ')'
Run Code Online (Sandbox Code Playgroud)
似乎eval方法引发的SyntaxError正在eval中的某个地方被拯救,而我没有机会自己处理它.
任何人都知道如何获得我想要的行为(即,我的'rescue'条款从'eval'中捕获错误)?
我正在使用一些包含在开始 - 救援块中的红宝石代码,但不知怎的,它设法仍然崩溃.
代码块看起来像这样:
# Retrieve messages from server
def get_messages
@connection.select('INBOX')
@connection.uid_search(['ALL']).each do |uid|
msg = @connection.uid_fetch(uid,'RFC822').first.attr['RFC822']
begin
process_message(msg)
add_to_processed_folder(uid) if @processed_folder
rescue
handle_bogus_message(msg)
end
# Mark message as deleted
@connection.uid_store(uid, "+FLAGS", [:Seen, :Deleted])
end
end
Run Code Online (Sandbox Code Playgroud)
鉴于此代码,我假设如果process_message或add_to_processed_folder无法执行,那么rescue将启动并调用handle_bogus_message.话虽这么说,我在生产环境中运行此代码,有时当我"获取"电子邮件消息(这是从rake任务运行)时,它会死于SyntaxError.
一看错误消息退房http://pastie.org/1028479 并不算process_message,它指的是相同的process_message以上.是否有任何理由为什么开始 - 救援不会抓住这个例外?
我有以下错误:
ActionController::RoutingError (No route matches [GET] "/images/favicon.ico")
Run Code Online (Sandbox Code Playgroud)
我想为error404页面显示不存在的链接.
我怎样才能做到这一点?
ruby exception-handling ruby-on-rails rescue ruby-on-rails-4
这是一个广泛的问题,但在Ruby编程时我会继续遇到这个问题.我来自一个很大的C和Java背景,当我使用库函数或方法时,我查看文档并查看错误返回的内容(通常在C中)或它可以抛出的异常(在Java中).
在Ruby中,情况似乎完全不同.刚才我需要解析从服务器收到的一些JSON:
data = JSON.parse(response)
Run Code Online (Sandbox Code Playgroud)
当然,在编写这段代码后我想到的第一件事就是如果输入不好怎么办?是否parse会在出错时返回nil,或者引发一些异常,如果是,那是哪些?
我查看文档(http://flori.github.com/json/doc/JSON.html#M000022),看看,简单地说:
"将JSON字符串源解析为Ruby数据结构并将其返回."
这只是我在Ruby中反复遇到的模式的一个例子.最初,我认为这是我正在使用的任何库的文档的一些缺点,但现在我开始觉得这是标准的做法,我的思维方式与Ruby程序员有点不同.有一些我不知道的惯例吗?
开发人员如何处理这个问题?
(是的,我确实查看了库方法的代码,并且可以了解引发了什么异常,但我不能100%确定,如果没有记录,我会感到不舒服,依赖它.)
编辑:看完前两个答案后,让我继续上面的JSON解析示例.
我怀疑我不应该这样做:
begin
data = JSON.parse(response)
raise "parse error" if data.nil?
rescue Exception => e
# blahblah
end
Run Code Online (Sandbox Code Playgroud)
因为我可以查看代码/测试并看到它似乎引发了一个ParserError错误(返回nil似乎不是Ruby中的标准做法).我是否正确地说建议的做法是:
begin
data = JSON.parse(response)
rescue JSON::ParserError => e
# blahblah
end
Run Code Online (Sandbox Code Playgroud)
...基于我ParserError通过查看代码和测试了解到的内容?
(我还编辑了这个例子,以澄清它是我正在解析的服务器的响应.)
在我的Rails 2.3.8应用程序中,我有一个例外的rescue_from代码,它在javascript操作期间抛出:
rescue_from ::Exception, :with => :show_js_errors
...
def show_js_errors exception
if request.format == :js
flash[:error] = 'some error occured'
render :update do |page|
page.redirect_to({:controller => '/home', :action => :index})
end
else
# use default error handling for non-JS requests
rescue_action_without_handler(exception)
end
end
Run Code Online (Sandbox Code Playgroud)
因此,如果ajax调用遇到错误,我的用户会收到错误消息.在Rails 3中,我不能简单地调用默认的错误处理,因为"without_handler"方法不再存在.
更新 doh
经过3个小时的搜索,我发布了这个,但发布后仅30分钟我就找到了解决方案.
只是重新提出异常.
由于您处于错误处理状态,因此不会对此异常进行进一步处理.
我最近了解到,如果rescue在该行出现问题,您可以使用一行代码(请参阅http://www.rubyinside.com/21-ruby-tricks-902.html提示#21).我有一些代码,看起来像这样:
if obj['key'] && obj['key']['key2'] && obj['key']['key2']['name']
name = obj['key']['key2']['name']
else
name = ''
end
Run Code Online (Sandbox Code Playgroud)
使用该rescue方法,我相信我可以将代码更改为以下内容:
name = obj['key']['key2']['name'] rescue ''
Run Code Online (Sandbox Code Playgroud)
如果在访问哈希的任何级别抛出零异常,它应该被救援抓住并给我'',这就是我想要的.我也可以选择设置名称,nil如果这是所需的行为.
这样做有什么危险吗?我问,因为这看起来好得令人难以置信.我有这么多丑陋的代码,我想摆脱它看起来像第一个代码示例.
我偶然发现了我的应用程序查找数据库中不存在的id的情况.抛出异常.当然,对于任何Web开发人员来说,这都是一个非常标准的情况.
感谢这个答案我知道使用救援处理的情况非常整齐,如下:
def show
@customer = Customer.find(params[:id])
rescue ActiveRecord::RecordNotFound #customer with that id cannot be found
redirect_to action: :index #redirect to index page takes place instead of crashing
end
Run Code Online (Sandbox Code Playgroud)
如果找不到客户,则用户被重定向到索引页面.这绝对没问题.
现在,这一切都很好,但我需要在show,edit,destroy等操作中进行相同的救援尝试,即每个需要特定id的控制器方法.
话虽如此,这是我的问题: 没有任何方法可以告诉我的控制器,如果它无法在任何方法中找到id,它将重定向到索引页面(或者,通常,执行特定的任务)?
Rails 4添加了一个异常ActionDispatch :: ParamsParser :: ParseError异常,但由于它在中间件堆栈中,它似乎无法在普通控制器环境中获救.在json API应用程序中,我想用标准错误格式进行响应.
这个要点显示了插入中间件以拦截和响应的策略.遵循这种模式我有:
application.rb中:
module Traphos
class Application < Rails::Application
....
config.middleware.insert_before ActionDispatch::ParamsParser, "JSONParseError"
end
end
Run Code Online (Sandbox Code Playgroud)
中间件是:
class JSONParseError
def initialize(app)
@app = app
end
def call(env)
begin
@app.call(env)
rescue ActionDispatch::ParamsParser::ParseError => e
[422, {}, ['Parse Error']]
end
end
end
Run Code Online (Sandbox Code Playgroud)
如果我在没有中间件的情况下运行测试,我会得到(spec):
Failures:
1) Photo update attributes with non-parseable json
Failure/Error: patch update_url, {:description => description}, "CONTENT_TYPE" => content_type, "HTTP_ACCEPT" => accepts, "HTTP_AUTHORIZATION" => @auth
ActionDispatch::ParamsParser::ParseError:
399: unexpected token at 'description=Test+New+Description]'
Run Code Online (Sandbox Code Playgroud)
这正是我所期望的(ParseError,我无法rescue_from). …