问题
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?
It seems that if I say phonelist.each do |phone|
that if phonelist is empty, then the block should not be executed.
But in my view (haml) I have - @myvar.phonelist.each do |phone|
and if phonelist is empty, it throws a NoMethodError.
I run into this a lot, and always workaround by adding an explicit check/branch for .blank? but it seems there should be an easier way to tell .each that empty means do nothing.
回答1:
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.
HOWEVER, this will still throw an exception if phonelist
is not an enumerable (e.g. an array).
回答2:
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.
phonelist = nil
phonelist.try(:each){|i| puts i}
回答3:
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.
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 !
回答4:
You're attempting to smack a band-aid on a larger problem.
Ruby has a concept of nil; can't get around it. If you are calling a method on nil
, then you are assuming it is valid, i.e., your design assumes it to be valid. 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| and if phonelist is empty, it throws a NoMethodError.
No. If phonelist
is not an object which implements .each
it throws an error. Very different.
You can always initialize it to an empty array if null, i.e., phonelist ||= []
, but I would prefer a design which ensures valid data whenever possible.
回答5:
If you get phonelist
from a hash (e.g. parsed JSON file), you may want to use fetch
with []
as the default.
phonelist = my_data.fetch('phonelist', [])
回答6:
Simply make sure empty phonelist
is a []
, instead of a nil
value.
Alternatively, a nil
value is falsey in Ruby, so you can use nil-punning
if phonelist
phonelist.each do |phone|
...
来源:https://stackoverflow.com/questions/9593705/rails-3-1-ruby-idiom-to-prevent-each-from-throwing-exception-if-nil