2012-01-19 50 views
13

我知道ActiveSupport提供的此功能。我如何获得JavaScript风格的哈希访问?

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

更新:

对不起,我应该提到,因为它不具有结构有each_pair方法我不能用openstruct。我事先不知道密钥,所以我不能使用openstruct。

+0

几乎相同的问题: - 混杂键http://stackoverflow.com/questions/2240535/ruby-hash-keys-as-methods-on-a-class –

+0

[红宝石的可能重复到方法名称?](http://stackoverflow.com/questions/6423484/ru by-hash-keys-to-method-names) –

回答

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 
6

您正在寻找OpenStruct

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

对不起,我应该提到我不能使用openstruct,因为它没有Struct所具有的each_pair方法。我手边不知道钥匙,所以我不能使用openstruct。 –

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

如果它只是一个小的脚本就可以安全地延长Hash本身

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

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

对于更复杂的应用程序,其中添加这种行为给所有哈希可能破坏其他代码或third0party宝石,使用模块和扩展每个实例

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