現在、私は次のことを行っていますが、より良い方法があるはずです:
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
。