現在、私は次のことを行っていますが、より良い方法があるはずです:
def birthday_defined?(map)
map && map[:extra] && map[:extra][:raw_info] && map[:extra][:raw_info][:birthday]
end
のみmap[:extra]が定義されている場合があり、上記のチェック済みコードを使用しないと、Nil 例外エラーの原因map[:extra][:raw_info]が存在しません。
Rails を使用している場合は、try(およびNilClass#try)を使用できます。
value = map.try(:[], :extra).try(:[], :raw_info).try(:[], :birthday)
これは少し繰り返しのように見えます。あるステップの結果を次のステップに送りながら、同じことを何度も繰り返しているだけです。このコード パターンは、隠れたインジェクションがあることを意味します。
value = [:extra, :raw_info, :birthday].inject(map) { |h, k| h.try(:[], k) }
mapこのアプローチは、あなたが念頭に置いているあらゆるパスにうまく一般化されます。
path = [ :some, :path, :of, :keys, :we, :care, :about ]
value = path.inject(map) { |h, k| h.try(:[], k) }
次に、 を見ることができますvalue.nil?。
もちろん、Rails を使用していない場合は、代わりのものが必要になりますが、tryそれは難しくありません。
私には2つの方法があります。どちらも同じコードですが、微妙に異なります。
# Method 1
def birthday_defined?(map)
map[:extra][:raw_info][:birthday] rescue nil # rescues current line
end
# Method 2
def birthday_defined?(map)
map[:extra][:raw_info][:birthday]
rescue # rescues whole method
nil
end
これはあなたのために働くはずです:
def birthday_defined?(map)
map
.tap{|x| (x[:extra] if x)
.tap{|x| (x[:raw_info] if x)
.tap{|x| (x[:birthday] if x)
.tap{|x| return x}}}}
end
begin/rescue ブロックを使用します。
begin
map[:extra][:raw_info][:birthday]
rescue Exception => e
'No birthday! =('
end
それはなぜそれをするのか慣用的です。はい、それは少し面倒かもしれません。
ただし、少し拡張したい場合はHash、キーパスのようなものでクールなことを行うことができます. ドット付きパス キー文字列を使用した Ruby ハッシュへのアクセスを参照してください。
def birthday_defined?
map.dig('extra.raw_info.birthday')
end
これは少しハックですが、うまくいきます:
def birthday_defined?(map)
map.to_s[":birthday"]
end
mapを含む場合は、条件ステートメントで:birthday評価される文字列を返しますが、true含まない場合:birthdayは を返しnilます。
注::birthdayこれは、キーが の複数の場所に表示される可能性がないことを前提としていますmap。