How can I get JavaScript style hash access?

后端 未结 4 1764
余生分开走
余生分开走 2021-02-19 11:05

I am aware of this feature provided by ActiveSupport.

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


        
相关标签:
4条回答
  • 2021-02-19 11:33

    You are looking for OpenStruct

    $ require 'ostruct'
    $ large_hash_obj = OpenStruct.new large_hash
    $ large_hash_obj.boy
    => "John"
    
    0 讨论(0)
  • 2021-02-19 11:36

    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.

    0 讨论(0)
  • 2021-02-19 11:38

    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
    
    0 讨论(0)
  • 2021-02-19 11:47

    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
    
    0 讨论(0)
提交回复
热议问题