我从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的答案是简洁和可读性的最佳折衷方案。谢谢大家。
答案 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的观点是有效的,这不太可读!而不是垃圾的方式,很多括号