如何在Ruby中返回值或有条件地引发错误?

时间:2012-06-20 06:41:54

标签: ruby

我从Rails模型调用API,如果API返回非200代码,我想引发错误。否则我想缓存/延迟加载数据。这是我的方法:

def data
    @data ||= SNL.get_list(name)
    raise StandardError, @data.inspect unless @data.success?
    @data
end

这有效,但我想知道我是否可以在一行中完成此任务。我尝试将and运算符与unless结合使用,但无法使其工作。

更新:我已经接受了tokland的回答,因为我要求一行,他/她提供了两个非常好的解决方案。最后我实际上要使用

def data
  @data ||= SNL.get_list(name)
  @data.success? ? @data : (raise StandardError, @data.inspect)
end

为了便于阅读。我只是讨厌让第三行返回@data,因为很少会引发异常。我觉得odiszapc的答案是简洁和可读性的最佳折衷方案。谢谢大家。

4 个答案:

答案 0 :(得分:2)

您可以使用terneray运算符。但是,我认为保持代码尽可能可读非常重要。通常根据我的经验,水平传播过多的代码通常有点难以理解。

您需要确定一件事。如果SNL.get_list(name)返回nil并且您尝试使用and运算符,则它将无效。

这个问题多次发生在我身上。示例示例:

nil and puts 'hello'

在你的irb中尝试这个。它不会起作用。这个问题已经无数次发生在我身上了。

答案 1 :(得分:2)

我不会因为写一个单行而感到紧张,但如果绝对必须,你可以使用tap

def data
  (@data ||= SNL.get_list(name)).tap { |d| d.success? or raise StandardError.new(d.inspect) }
end

还有短路逻辑:

def data
  (@data ||= SNL.get_list(name)).success? && @data or
    raise StandardError.new(@data.inspect) }
end

答案 2 :(得分:1)

也许

def data
  @data ||= SNL.get_list(name)
  @data.success? ? @data : (raise StandardError, @data.inspect)
end

或者我不确定,例如:

def data
  (@data ||= SNL.get_list(name)).success? ? @data : (raise StandardError, @data.inspect)
end

答案 3 :(得分:1)

def data
    (@data ||= SNL.get_list(name)).success? ? @data :  raise(StandardError, @data.inspect)
end

再次@Sohaib的观点是有效的,这不太可读!而不是垃圾的方式,很多括号