【问题标题】:how to properly rescue this statement in ruby?如何在 ruby​​ 中正确地挽救这个语句?
【发布时间】:2017-04-10 22:51:21
【问题描述】:

我有一个厨师资源,我刚刚在食谱中添加了带有 cookstyle 的 linting。我在食谱中有这一行:

existing_value = key.to_s.split('.').inject(node.elasticsearch) { |result, attr| result[attr] } rescue nil if existing_value.nil?

它导致 linter 出错。我尝试了几件事,但我不确定如何说同样的话并通过 lint 测试。

 Style/RescueModifier: Avoid using rescue in its modifier form

如果我完全删除了救援语句,则会导致此异常:

Chef::Mixin::Template::TemplateError (undefined method `[]' for nil:NilClass) on line #52:
    ...
    52: <%= print_value 'action.destructive_requires_name' -%>        
    ...

【问题讨论】:

  • 这是一个包罗万象的rescue,在实践中真的很糟糕。您可以删除rescue nil 部分并使其仍然正常工作吗?如果不是,它会引发什么异常?
  • key 的值是多少?请阅读“minimal reproducible example”和链接页面。错误告诉我们result 为零。
  • key 的值,在此示例中的第 52 行 action.destructive_requires_namenil,它在我发布的异常的输出中。
  • 一个小问题,请不要使用chefstyle,这是针对厨师本身的。您想使用 cookstyle 用于烹饪书。
  • 这实际上是烹饪风格。我的错。

标签: ruby chef-infra rubocop


【解决方案1】:

因此,如果您使用的是较新的 Chef 版本,我们实际上有一种方法。你可以这样做:

existing_value ||= node.read("elasticsearch.#{key}")  

剩下的我们会处理。

【讨论】:

    【解决方案2】:

    虽然#coderanger的解决方案更好,但linter希望你使用长救援表单

    begin
      existing_value = key.to_s.split('.').inject(node.elasticsearch) { |result, attr| result[attr] } 
    rescue 
      nil
    end if existing_value.nil?
    

    或通常认为更好

    if existing_value.nil?
      begin
        existing_value = key.to_s.split('.').inject(node.elasticsearch) { |result, attr| result[attr] } 
      rescue 
        nil
      end
    end
    

    我还将rescue 更改为更具体的rescue Chef::Mixin::Template::TemplateError,拯救所有异常可能不是您想要的(即您不想隐藏真正的异常)

    【讨论】:

    • 实际的异常是不同的,我们只是包装了所有来自 Erb 的错误,以便它们以一些特殊的逻辑显示。
    • 有无数文章解释了为什么这是一件坏事。例如,您不应该捕获 SystemExit 或 OutOfMemory 错误,因为抛出这些错误还有其他原因。您至少应该将其限制为 StandardError 的子类
    猜你喜欢
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 2013-10-22
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    相关资源
    最近更新 更多