2

APIからJSONネストされたハッシュ(またはハッシュの配列)を取得しているとしましょう

@example = {"results" = > {{"poop" => "shoop"},{"foo" => {"shizz" => "fizz", "nizzle"=>"bizzle"}}}

上記のネストされたハッシュのYAMLマークアップ

  - poop: shoop
  - foo:
    shizz: fizz
    nizzle: bizzle

それでは、ハッシュからActiveRecordを使用してdbエントリを作成しましょう。これは正常に機能します。

Thing.create!(:poop  => @example["results"]["poop"],
                :shizz => @example["results"]["foo"]["shizz"],
                :nizzle=> @example["results"]["foo"]["nizzle"])

しかし、「foo」が空またはnilの場合はどうなりますか?たとえば、APIの結果に「名」、「姓」#などの「人」ハッシュが含まれている場合、データがない場合、「人」ハッシュは通常空になります。つまり、その中のハッシュは空になりません。存在。

@example = {"results" = > {{"poop" => "shoop"},{"foo" => nil }}

  Thing.create!(:poop  => @example["results"]["poop"],
                :shizz => @example["results"]["foo"]["shizz"],
                :nizzle=> @example["results"]["foo"]["nizzle"])

  NoMethodError: You have a nil object when you didn't expect it! 
  You might have expected an instance of Array. 
  The error occurred while evaluating nil.[]

これを処理するための最良の方法は何ですか?

4

4 に答える 4

4

nil私はしばらく前に敏感なHash#get方法に出くわしました。

class Hash
  def get(key, default=nil)
    key.split(".").inject(self){|memo, key_part| memo[key_part] if memo.is_a?(Hash)} || default
  end
end

h = { 'a' => { 'b' => { 'c' => 1 }}}
puts h.get "a.b.c"    #=> 1
puts h.get "a.b.c.d"  #=> nil
puts h.get "not.here" #=> nil

この種のJSONドリルには非常に便利です。

それ以外の場合は、次のようなことを行う必要があります。

h['a'] && h['a']['b'] && h['a']['b']['c']

そして、それはただひどいです。

于 2011-12-12T19:16:58.707 に答える
3

Ruby 2.3.0 では、両方で呼び出される新しいメソッドがdig導入され、この問題が完全に解決されました。HashArray

value = hash.dig(:a, :b)

nilいずれかのレベルでキーが欠落している場合に返されます。

于 2016-01-06T03:06:03.987 に答える
2

先に進み、すべての Hash 結果をHashie Mashに渡し始めました。そうすれば、それらは Ruby オブジェクトのように振る舞い、チャンピオンのように nil に応答します!

于 2012-01-25T19:23:48.967 に答える
2

Rails を使用している場合 (Ruby 1.9 かどうかは不明):

h = {"a"=>1}
h.try(:[],"a") #1
h.try(:[],"b") #nil

h2 = {"c"=>{"d"=>1}}
h2.try(:[],"c").try(:[],"d")   #1
h2.try(:[],"a").try(:[],"foo") #nil

# File activesupport/lib/active_support/core_ext/object/try.rb, line 28
def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    __send__(*a, &b)
  end
end

于 2011-12-12T19:33:04.620 に答える