【问题标题】:Rescue won't rescue in Rails救援不会在 Rails 中救援
【发布时间】:2011-07-01 19:13:58
【问题描述】:

我正在编写一个简单的应用程序来处理 POSTed CSV 文件,并针对无效输入(例如非 CSV 文件)对其进行测试。我正在使用 CSV::Reader.parse 命令在控制器方法中解析 CSV,如下所示:

@parsed_file = CSV::Reader.parse(params[:file]) rescue []

但是,尽管有救援声明,但当输入不正确的提交时,我仍然会收到未捕获的 CSV::IllegalFormatError。我在这里错过了什么?

谢谢!

【问题讨论】:

  • 你试过用括号括起来吗?像这样@parsed_file = (CSV::Reader.parse(params[:file]) rescue [])。你用的是什么版本的红宝石,这对我来说很好。
  • 是的,这对我也不起作用。我正在使用 1.8.7。这对我来说没有任何意义......
  • 这行得通吗? @parsed_file = raise CSV::IllegalFormatError rescue nil 如果没有,如果您在测试环境之外执行(即通过网络服务器),它是否有效
  • 如果这就是您的要求,则始终为 @parsed_file 分配 nil 的值(与给定文件无关)。
  • 这是一个很好的测试来看看救援是否真的有效:) 看起来好像是这样,我的猜测是 ruby​​ 奇怪地对你的操作进行分组。尝试使用 begin 而不是 parens 像 @parsed_file = begin CSV::Reader.parse(params[:file]) rescue [] end

标签: ruby-on-rails exception csv user-input rescue


【解决方案1】:

你需要传递一个文件句柄来解析:

@parsed_file = CSV::Reader.parse(File.open(params[:file], 'rb')) rescue []

【讨论】:

  • 感谢您的回复...尽管您的修改不再出现任何错误,但这似乎破坏了原始的 CSV 解析功能(正常工作)。现在看起来@parsed_file 是空的,无论文件是否有效。
  • 对不起,我有一个错字。现在怎么样?
  • 不,更多相同,不幸的是......无论提交的文件是否为有效的 CSV,它的行为都是相同的,也就是说总是抛出异常,并且总是被 @parsed_file已分配 []。
  • 我删除了“rescue []”子句以查看实际抛出了什么错误;这是“无法将 Tempfile 转换为字符串”的 TypeError。
  • 啊,这是一个临时文件。应该猜到了如果你保存它然后解析会发生什么?如果您在解析 CSV 之前它可能是相同的。如果你这样做rescue CSV::IllegalFormatError []会发生什么?
【解决方案2】:

我最终不得不对 CSV::Reader 类进行猴子补丁以正确处理异常。我仍然不确定为什么它没有被控制器捕获,但这是我最终编写的代码:

class CSV
  class Reader
    def each
      while true
        row = []
        parsed_cells = get_row(row) rescue 0 
        if parsed_cells == 0
          break
        end
        yield(row)
      end
      nil
    end
  end
end

请注意在调用get_row 之后的rescue 0,它在原始文件中不存在。绝对是一个丑陋的黑客,但它会满足我的目的。

如果有人能解释为什么异常没有在控制器中被捕获,我很乐意为他们的正确答案加分。

【讨论】:

    【解决方案3】:

    听起来好像您的CSV::IllegalFormatError 没有正确继承RuntimeError。或者RuntimeError 已更改为不是StandardError 的子类。

    只有子类StandardError 的错误才会被默认救援块捕获。为了验证这个理论,试试

    @parsed_file = begin 
      CSV::Reader.parse(params[:file]) 
    rescue StandardError
      puts "I caught a StandardError"
      []
    rescue Exception => e
      puts "I caught #{e.class}->#{e.class.superclass}->#{e.class.superclass.superclass}"
      []
    end
    

    这可以解释为什么我(可能还有其他人)不能重复这个问题。

    无论在何种情况下明确使用Exception 都应该有效,并且比猴子补丁更干净。

    【讨论】:

    • 您的解释对我来说很有意义,我对此寄予厚望,但是当我尝试您的代码 sn-p 时,使用非 CSV 时我仍然得到一个未捕获的 IllegalFormatError提交。对于可能发生的事情还有其他想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 2023-01-13
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多