4

現在、私は次のことを行っていますが、より良い方法があるはずです:

def birthday_defined?(map)
    map && map[:extra] && map[:extra][:raw_info] && map[:extra][:raw_info][:birthday]
end

のみmap[:extra]が定義されている場合があり、上記のチェック済みコードを使用しないと、Nil 例外エラーの原因map[:extra][:raw_info]が存在しません。

4

6 に答える 6

1

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それは難しくありません。

于 2012-10-22T17:40:17.263 に答える
1

私には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
于 2012-10-22T17:17:26.690 に答える
0

これはあなたのために働くはずです:

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
于 2012-10-22T20:18:26.317 に答える
0

begin/rescue ブロックを使用します。

begin
  map[:extra][:raw_info][:birthday]
rescue Exception => e
  'No birthday! =('
end
于 2012-10-22T17:12:59.607 に答える
0

それはなぜそれをするのか慣用的です。はい、それは少し面倒かもしれません。

ただし、少し拡張したい場合はHash、キーパスのようなものでクールなことを行うことができます. ドット付きパス キー文字列を使用した Ruby ハッシュへのアクセスを参照してください。

def birthday_defined?
  map.dig('extra.raw_info.birthday')
end
于 2012-10-22T17:13:07.890 に答える
0

これは少しハックですが、うまくいきます:

def birthday_defined?(map)
    map.to_s[":birthday"]
end

mapを含む場合は、条件ステートメントで:birthday評価される文字列を返しますが、true含まない場合:birthdayは を返しnilます。

注::birthdayこれは、キーが の複数の場所に表示される可能性がないことを前提としていますmap

于 2012-10-22T18:29:14.000 に答える