3

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

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

这行得通,但我想知道我是否可以在一行中完成此操作。我尝试将and运算符与 an 结合使用,unless但无法正常工作。

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

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

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

4

4 回答 4

3

我不会紧张写一个单行,但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
于 2012-06-20T07:16:46.647 回答
2

您可以只使用三元运算符。但是,我认为让您的代码尽可能具有可读性非常重要。一般来说,根据我的经验,水平扩展太多的代码通常有点难以理解。

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

这个问题在我身上发生过无数次。一个示例:

nil and puts 'hello'

在你的 irb 试试这个。它行不通。这个问题在我身上发生过无数次。

于 2012-06-20T06:58:53.620 回答
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
于 2012-06-20T06:52:33.493 回答
1

尝试

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

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

于 2012-06-20T07:15:05.110 回答