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

こ雲淡風輕ζ 提交于 2019-12-03 22:13:28
Ed S.

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.

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}

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 !

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', [])

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|
     ...
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!