.each
を使用して、オブジェクトがnilまたは空の場合にエラーをスローしないようにする方法はありますか(nil/blankテストを追加せずに)?
phonelist.each do |phone|
と言うと、phonelistが空の場合、ブロックは実行されるべきではないようです。
しかし、私の見解(haml)では- @myvar.phonelist.each do |phone|
があり、phonelistが空の場合、NoMethodErrorがスローされます。
私はこれに何度も遭遇し、.blankの明示的なチェック/ブランチを追加することで常に回避策を講じていますか?しかし、空は何もしないことを意味することを伝える簡単な方法があるはずです。
まだ誰もこれを提案していないとは信じられません:
(@myvar.phonelist || []).each do |phone|
...
phonelist
がnil
の場合、each
は空の配列でループし、ブロックを0回実行します。
ただし、phonelist
が列挙可能でない場合(配列など)、これでも例外がスローされます。
try メソッドを使用してnilで.eachを呼び出すことができるため、オブジェクトがnilまたは空の場合でもエラーはスローされません。
phonelist = nil
phonelist.try(:each){|i| puts i}
単に以下を実行します。
Array(phonelist).each do |phone|
#deal with your phone
end
Array(my_variable)は、my_variableがnilの場合に配列を返すようにします。
My_variableがすでに配列である場合、新しい配列は作成されないため、どこでも安全かつ軽量に使用できます。
あなたはより大きな問題でバンドエイドを叩こうとしています。
Rubyにはnilの概念があります。それを回避することはできません。 nil
でメソッドを呼び出す場合は、それが有効であると想定しています。つまり、designは有効であると想定しています。だから問題は本当にです:あなたのデザインの穴はどこにありますか?なぜあなたの仮定は間違っているのですか?
ここでの問題は、それをサポートしていないオブジェクトに対して任意のメソッドを呼び出すことができないということではありません。問題は、明らかに常にそうであるとは限らない場合に、データが有効であると見なされることです。
しかし、私の見解では(haml)私は持っています-@ myvar.phonelist.each do | phone |また、phonelistが空の場合、NoMethodErrorがスローされます。
いいえ。phonelist
.each
を実装するオブジェクトではないの場合、エラーがスローされます。とても違う。
Nullの場合、つまりphonelist ||= []
の場合はいつでも空の配列に初期化できますが、可能な限り有効なデータを保証する設計をお勧めします。
ハッシュ(解析されたJSONファイルなど)からphonelist
を取得する場合は、デフォルトとして[]
を指定してfetch
を使用することをお勧めします。
phonelist = my_data.fetch('phonelist', [])
空のphonelist
がnil
値ではなく、[]
であることを確認してください。
または、Rubyではnil
値がfalseであるため、 nil-punning を使用できます。
if phonelist
phonelist.each do |phone|
...