用nils遍历ruby嵌套散列?
问题描述:
让我们说我从API取回一个JSON嵌套散列(或散列数组)用nils遍历ruby嵌套散列?
@example = {"results" = > {{"poop" => "shoop"},{"foo" => {"shizz" => "fizz", "nizzle"=>"bizzle"}}}
YAML标记中嵌套的哈希上述
- poop: shoop
- foo:
shizz: fizz
nizzle: bizzle
现在让我们去作数据库条目与ActiveRecord哈希。这工作正常。
Thing.create!(:poop => @example["results"]["poop"],
:shizz => @example["results"]["foo"]["shizz"],
:nizzle=> @example["results"]["foo"]["nizzle"])
但是如果'foo'为空或无?例如,如果一个API结果有一个带有“名字”,“姓氏”#等的“person”散列,那么如果没有数据,那么“person”散列通常是空的,这意味着它内部的散列不会“不存在。
@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.[]
处理这个问题的最好方法是什么?
答
我来过一个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']
而这只是吮吸。
答
如果您使用的轨道(不知道它在红宝石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
+0
我喜欢Rails应用程序的这种解决方案,但我正在寻找更低级别的纯Ruby解。我会试试这个,谢谢! – thoughtpunch
答
确实很有趣,如何“耗尽”备忘录散列 – maprihoda
光滑 - 这将派上用场 – klochner
所以我会制作一个自定义的类来扩展系统的哈希类,或者我会将这个'get'方法的猴子修补成“哈希”? – thoughtpunch