如何获得JavaScript样式的哈希访问?

时间:2012-01-19 22:29:23

标签: ruby object hash

我知道ActiveSupport提供的这项功能。

h = ActiveSupport::OrderedOptions.new
h.boy = 'John'
h.girl = 'Mary'
h.boy  # => 'John'
h.girl # => 'Mary'

但是我已经有一个大哈希,我想使用点表示法访问该哈希值。这就是我试过的:

large_hash = {boy: 'John', girl: 'Mary'}
h = ActiveSupport::OrderedOptions.new(large_hash)
h.boy # => nil

那不起作用。我怎样才能做到这一点。

我正在使用ruby 1.9.2

更新

很抱歉我应该提到我不能使用openstruct,因为它没有Struct所具有的each_pair方法。我事先不知道密钥所以我不能使用openstruct。

4 个答案:

答案 0 :(得分:9)

OpenStruct应该很好地为此工作。

如果您想了解它的工作原理,或者想要制作自定义版本,请从以下内容开始:

h = { 'boy' => 'John', 'girl' => 'Mary' }

class << h
  def method_missing m
    self[m.to_s]
  end
end

puts h.nothing
puts h.boy
puts h.girl

答案 1 :(得分:6)

您正在寻找OpenStruct

$ require 'ostruct'
$ large_hash_obj = OpenStruct.new large_hash
$ large_hash_obj.boy
=> "John"

答案 2 :(得分:4)

I created my own gem for this,我一直在我的所有项目中使用它。似乎只是做你需要的:

large_hash = { boy: 'John', girl: 'Mary' }
r = Ribbon.wrap large_hash

r.boy
 => "John"

r.girl
 => "Mary"

r.keys
 => [:boy, :girl]

r.each_pair { |key, value| puts "#{key} => #{value}" }
boy => John
girl => Mary

会喜欢一些反馈。

答案 3 :(得分:3)

如果它只是一个小脚本,那么扩展Hash本身

是安全的
class Hash
  def method_missing sym,*
    fetch(sym){fetch(sym.to_s){super}}
  end
end

method_missing是一种神奇的方法,只要您的代码尝试调用不存在的方法,就会调用该方法。 Ruby将在运行时拦截失败的调用,让你处理它,这样你的程序就可以优雅地恢复。上面的实现尝试使用方法名称作为符号访问哈希,使用方法名称作为字符串,并最终失败,Ruby的内置方法丢失错误。

对于更复杂的应用程序,将此行为添加到所有哈希值可能会破坏其他代码或第三方域,请使用模块并扩展每个实例

module H
  def method_missing sym,*
    fetch(sym){fetch(sym.to_s){super}}
  end
end

the = { answer: 42 }
the.extend(H)
the.answer # => 42

为了更方便,您甚至可以将模块传播到嵌套哈希

module H
  def method_missing sym,*
    r = fetch(sym){fetch(sym.to_s){super}}
    Hash === r ? r.extend(H) : r
  end
end 

the = { answer: { is: 42 } }
the.extend(H)
the.answer.is # => 42