Rails 3.1: идиома Ruby для предотвращения исключения .each, если nil? - PullRequest
25 голосов
/ 07 марта 2012

Есть ли способ использовать .each, чтобы он не выдавал ошибку, если объект нулевой или пустой (без добавления дополнительного теста ноль / пробел?

Похоже, что если я скажу phonelist.each do |phone|, что если фонлист не указан, блок не должен выполняться.

Но, на мой взгляд (хамл), у меня есть - @myvar.phonelist.each do |phone|, и если фонеллист пуст, он выдает ошибку NoMethodError.

Я часто сталкиваюсь с этим, и всегда обходной путь, добавляя явную проверку / ветвь для .blank? но, кажется, должен быть более простой способ сказать .each, что пустые средства ничего не делают.

Ответы [ 5 ]

44 голосов
/ 07 марта 2012

Вы можете использовать метод try для вызова .each для nil, чтобы он не выдавал ошибку, если объект равен nil или пуст.

phonelist = nil
phonelist.try(:each){|i| puts i}
29 голосов
/ 19 сентября 2013

Просто сделайте следующее:

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

Массив (my_variable) обеспечит возврат массива, если my_variable равен nil.

Он не создает новый массив, если my_variable уже существуетмассив, так что его можно безопасно и легко использовать где угодно!

16 голосов
/ 07 марта 2012

Вы пытаетесь ударить бинтом по более крупной проблеме.

В Ruby есть понятие ноль; не могу обойти это. Если вы вызываете метод на nil, то вы предполагаете, что он действителен, т. Е. Ваш дизайн предполагает, что он действителен. Таким образом, вопрос на самом деле: где дыра в вашем дизайне? Почему ваше предположение неверно?

Проблема здесь не в том, что вы не можете вызывать произвольные методы для объекта, который его не поддерживает; проблема в том, что ваши данные считаются действительными, когда очевидно, что это не всегда так.

Но, на мой взгляд (хамл), у меня есть - @ myvar.phonelist.each do | phone | и если фонетист пуст, он выдает ошибку NoMethodError.

Нет. Если phonelist не является объектом, который реализует .each, он выдает ошибку. Очень разные.

Вы всегда можете инициализировать его пустым массивом, если он равен нулю, т. Е. phonelist ||= [], но я бы предпочел конструкцию, которая обеспечивает достоверность данных, когда это возможно.

2 голосов
/ 05 января 2016

Если вы получаете phonelist из хэша (например, проанализированный файл JSON), вы можете использовать fetch с [] по умолчанию.

phonelist = my_data.fetch('phonelist', [])
1 голос
/ 16 марта 2018

Просто убедитесь, что пустое phonelist - это [], а не nil.

В качестве альтернативы, значение nil в Faly является ложным, поэтому вы можете использовать nil-паннинг

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