How can I get JavaScript style hash access?

2020-07-03 04:03发布

I am aware of this feature provided by ActiveSupport.

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

However I already have a large hash and I want to access that hash using dot notation. This is what I tried:

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

That did not work. How can I make this work.

I am using ruby 1.9.2

Update:

Sorry I should have mentioned that I can't use openstruct because it does not have each_pair method which Struct has. I do not know keys beforehand so I can't use openstruct.

标签: ruby object hash
4条回答
疯言疯语
2楼-- · 2020-07-03 04:34

I created my own gem for this, and I've been using it in all my projects. Seems to do just what you need:

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

Would love some feedback.

查看更多
混吃等死
3楼-- · 2020-07-03 04:36

If it’s just a small script it’s safe to extend Hash itself

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

method_missing is a magic method that is called whenever your code tries to call a method that does not exist. Ruby will intercept the failing call at run time and let you handle it so your program can recover gracefully. The implementation above tries to access the hash using the method name as a symbol, the using the method name as a string, and eventually fails with Ruby's built-in method missing error.

For a more complex application, where adding this behavior to all hashes might break other code or third0party gems, use a module and extend each instance

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

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

and for greater convenience you can even propagate the module down to nested hashes

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
查看更多
叛逆
4楼-- · 2020-07-03 04:37

You are looking for OpenStruct

$ require 'ostruct'
$ large_hash_obj = OpenStruct.new large_hash
$ large_hash_obj.boy
=> "John"
查看更多
叛逆
5楼-- · 2020-07-03 04:44

OpenStruct should work nicely for this.

If you want to see how it works, or perhaps make a customized version, start with something like this:

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
查看更多
登录 后发表回答