web-dev-qa-db-ja.com

Rails 3.1:Ruby .eachがnilの場合に例外をスローしないようにするイディオム?

.eachを使用して、オブジェクトがnilまたは空の場合にエラーをスローしないようにする方法はありますか(nil/blankテストを追加せずに)?

phonelist.each do |phone|と言うと、phonelistが空の場合、ブロックは実行されるべきではないようです。

しかし、私の見解(haml)では- @myvar.phonelist.each do |phone|があり、phonelistが空の場合、NoMethodErrorがスローされます。

私はこれに何度も遭遇し、.blankの明示的なチェック/ブランチを追加することで常に回避策を講じていますか?しかし、空は何もしないことを意味することを伝える簡単な方法があるはずです。

25
jpw

まだ誰もこれを提案していないとは信じられません:

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

phonelistnilの場合、eachは空の配列でループし、ブロックを0回実行します。

ただし、phonelistが列挙可能でない場合(配列など)、これでも例外がスローされます。

2

try メソッドを使用してnilで.eachを呼び出すことができるため、オブジェクトがnilまたは空の場合でもエラーはスローされません。

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

単に以下を実行します。

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

Array(my_variable)は、my_variableがnilの場合に配列を返すようにします。

My_variableがすでに配列である場合、新しい配列は作成されないため、どこでも安全かつ軽量に使用できます。

30
Arkan

あなたはより大きな問題でバンドエイドを叩こうとしています。

Rubyにはnilの概念があります。それを回避することはできません。 nilでメソッドを呼び出す場合は、それが有効であると想定しています。つまり、designは有効であると想定しています。だから問題は本当にです:あなたのデザインの穴はどこにありますか?なぜあなたの仮定は間違っているのですか?

ここでの問題は、それをサポートしていないオブジェクトに対して任意のメソッドを呼び出すことができないということではありません。問題は、明らかに常にそうであるとは限らない場合に、データが有効であると見なされることです。

しかし、私の見解では(haml)私は持っています-@ myvar.phonelist.each do | phone |また、phonelistが空の場合、NoMethodErrorがスローされます。

いいえ。phonelist.eachを実装するオブジェクトではないの場合、エラーがスローされます。とても違う。

Nullの場合、つまりphonelist ||= []の場合はいつでも空の配列に初期化できますが、可能な限り有効なデータを保証する設計をお勧めします。

16
Ed S.

ハッシュ(解析されたJSONファイルなど)からphonelistを取得する場合は、デフォルトとして[]を指定してfetchを使用することをお勧めします。

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

空のphonelistnil値ではなく、[]であることを確認してください。

または、Rubyではnil値がfalseであるため、 nil-punning を使用できます。

if phonelist
   phonelist.each do |phone|
     ...
1
user7610