简体   繁体   English

Rails 3.1:Ruby 成语防止.each 如果为零则抛出异常?

[英]Rails 3.1: Ruby idiom to prevent .each from throwing exception if nil?

Is there a way to use .each so it does not throw an error if the object is nil or empty (without adding an additional nil/blank test?有没有办法使用.each因此如果 object 为 nil 或为空(不添加额外的 nil/空白测试?

It seems that if I say phonelist.each do |phone|似乎如果我说phonelist.each do |phone| that if phonelist is empty, then the block should not be executed.如果 phonelist 为空,则不应执行该块。

But in my view (haml) I have - @myvar.phonelist.each do |phone|但在我看来(haml)我有- @myvar.phonelist.each do |phone| and if phonelist is empty, it throws a NoMethodError.如果电话列表为空,它会抛出一个 NoMethodError。

I run into this a lot, and always workaround by adding an explicit check/branch for.blank?我经常遇到这个问题,并且总是通过添加一个明确的检查/分支 for.blank 来解决这个问题? but it seems there should be an easier way to tell.each that empty means do nothing.但似乎应该有一个更简单的方法来告诉。每个空意味着什么都不做。

You can use the try method to call .each on a nil so it does not throw an error if the object is nil or empty.您可以使用try方法在 nil 上调用 .each ,因此如果对象为 nil 或为空,它不会抛出错误。

phonelist = nil
phonelist.try(:each){|i| puts i}

Simply do the following:只需执行以下操作:

Array(phonelist).each do |phone|
  #deal with your phone
end

Array(my_variable) will ensure to return an array if my_variable is nil.如果 my_variable 为零,则 Array(my_variable) 将确保返回一个数组。

It doesn't create a new Array if my_variable is already an array, so it is safe and light to use it wherever you want !如果 my_variable 已经是一个数组,它不会创建一个新的数组,所以在任何你想要的地方使用它都是安全和轻松的!

You're attempting to smack a band-aid on a larger problem.您正试图在更大的问题上使用创可贴。

Ruby has a concept of nil; Ruby 有一个 nil 的概念; can't get around it.无法绕过它。 If you are calling a method on nil , then you are assuming it is valid, ie, your design assumes it to be valid.如果您在nil上调用一个方法,那么您假设它是有效的,即您的设计假设它是有效的。 So the question really is: where is the hole in your design?所以真正的问题是:你的设计中的漏洞在哪里? Why is your assumption incorrect?为什么你的假设不正确?

The problem here is not that you cannot call arbitrary methods on an object which does not support it;这里的问题不是你不能在不支持它的对象上调用任意方法; the problem is that your data is assumed to be valid when obviously that is not always the case.问题是您的数据被认为是有效的,而显然情况并非总是如此。

But in my view (haml) I have - @myvar.phonelist.each do |phone|但在我看来(haml)我有 - @myvar.phonelist.each do |phone| and if phonelist is empty, it throws a NoMethodError.如果 phonelist 为空,则抛出 NoMethodError。

No. If phonelist is not an object which implements .each it throws an error.否。如果phonelist不是实现.each的对象, .each引发错误。 Very different.非常不一样。

You can always initialize it to an empty array if null, ie, phonelist ||= [] , but I would prefer a design which ensures valid data whenever possible.如果为空,您始终可以将其初始化为空数组,即phonelist ||= [] ,但我更喜欢一种设计,以确保尽可能确保有效数据。

Can't believe no one has suggested this yet:不敢相信还没有人提出这个建议:

(@myvar.phonelist || []).each do |phone|
   ...

If phonelist is nil , the each will loop on the empty array, executing the block zero times.如果phonelistnileach将在空数组上循环,执行块零次。

HOWEVER, this will still throw an exception if phonelist is not an enumerable (eg an array).但是,如果phonelist不是可枚举的(例如数组),这仍然会引发异常。

如果您从散列(例如解析的 JSON 文件)中获取phonelist列表,您可能希望使用带有[]作为默认值的fetch

phonelist = my_data.fetch('phonelist', [])

Simply make sure empty phonelist is a [] , instead of a nil value.只需确保空phonelist[] ,而不是nil值。

Alternatively, a nil value is falsey in Ruby, so you can use nil-punning或者,一个nil值在 Ruby 中是假的,所以你可以使用nil-punning

if phonelist
   phonelist.each do |phone|
     ...

what i've seen done a lot is:我经常看到的是:

@myvar.phonelist.each do |phone|
  # ...
end unless @myvar.phonelist.nil?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM