Ruby尝试不处理异常

时间:2017-10-04 09:55:04

标签: ruby-on-rails ruby

我有以下示例ruby代码:

def example_method(obj)
    ExampleClass.new(color1: @theme.try(obj['color1'].to_sym))
end

哪个应该将obj['color1']作为符号或nil传递给该类。

但如果未通过color1,我会收到错误:NoMethodError: undefined method 'to_sym' for nil:NilClass

try方法不应该处理异常吗?

更新:基于评论...我通过三元组解决了这个问题:

ExampleClass.new(color1: obj['color1'].present? ? @brand_theme.try(obj['color1'].try(:to_sym)) : nil)

3 个答案:

答案 0 :(得分:3)

您可以编写辅助方法:

def theme_color(name)
  return unless name
  return unless @theme.respond_to?(name)
  @theme.public_send(name)
end

def example_method(obj)
  ExampleClass.new(color1: theme_color(obj['color1']))
end
如果参数为theme_color

nil会返回nil,即obj['color1']。如果nil未响应给定方法,它也会返回theme。否则,它将调用name指定的方法。

请注意,respond_to?public_send接受字符串或符号,因此不需要to_sym

您还可以将辅助方法定义为@theme类的实例方法:

class Theme
  def color(name)
    return unless name
    return unless respond_to?(name)
    public_send(name)
  end

  def red
    'FF0000'
  end
end

@theme = Theme.new
@theme.red            #=> "FF0000"
@theme.color(:red)    #=> "FF0000"
@theme.color('red')   #=> "FF0000"
@theme.color('green') #=> nil
@theme.color(nil)     #=> nil

通过以下方式调用它:

def example_method(obj)
  ExampleClass.new(color1: @theme.color(obj['color1']))
end

请注意,这些方法(使用public_sendtry)允许您在@theme对象上调用任意方法。将颜色保留在散列中可能更安全。

答案 1 :(得分:2)

try对象上调用@theme。抛出nil错误是因为obj['color1']返回nil,然后在to_sym上调用nil

您必须将代码更改为

 ExampleClass.new(color1: @theme.try(obj['color1'].try(:to_sym) || ''))

抓住那个。

然后你必须美化代码。

美化效果如何取决于用例,所以我只能提供一些通用指针。一种方法是将默认值设为avoid having to deal with the null object

不是传递nil,而是简单地返回一个默认值:

color_key = obj.fetch('color') { 'default_color' }.to_sym
ExampleClass.new(color1: @theme.send(color_key)))

这使用了fetch method,可以返回默认值。这样,您将始终定义一个值。

答案 2 :(得分:2)

来自评论:

  

在此示例中,obj['color1']将为零。所以我们通过nil尝试。

是的,这是一个错误。你无法调用没有名字的方法。 从技术上讲,你可以通过.try(obj['color'].to_s)来避免错误,但这是错误的。

如果不存在,我会明确检查存在并提前保释。

def example_method(obj)
  return unless obj['color1'].present?

  ExampleClass.new(color1: @theme.try(obj['color1']))
end