2012-01-19 9 views
13

Conozco esta característica proporcionada por ActiveSupport.¿Cómo puedo obtener acceso hash de estilo JavaScript?

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

Sin embargo, ya tengo un hash grande y quiero acceder a ese hash utilizando la notación de puntos. Esto es lo que probé:

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

Eso no funcionó. ¿Cómo puedo hacer que esto funcione?

estoy usando ruby ​​1.9.2

Actualización:

sentimos que debería haber mencionado que no puedo usar openstruct porque no tiene each_pair método que tiene Struct. No sé las claves de antemano, así que no puedo usar openstruct.

+0

Casi una pregunta idéntica: http://stackoverflow.com/questions/2240535/ruby-hash-keys-as-methods-on-a-class –

+0

posible duplicado de llaves [Ruby - hash para nombres de métodos?] (http://stackoverflow.com/questions/6423484/ru by-hash-keys-to-method-names) –

Respuesta

9

OpenStruct debería funcionar muy bien para esto.

Si quieres ver cómo funciona, o tal vez hacer una versión personalizada, comenzar con algo como esto:

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

Usted está buscando OpenStruct

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

Lo siento, debería haber mencionado que no puedo usar openstruct porque no tiene el método each_pair que tiene Struct. No conozco las claves de antemano, así que no puedo usar openstruct. –

4

I created my own gem for this, y yo he estado usando en todos mis proyectos. Parece que hace justo lo que necesita:

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 

Me encantaría recibir algún comentario.

3

Si es sólo un pequeño script que es seguro para extender Hash

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

method_missing es un método mágico que se llama cuando el código intenta llamar a un método que no existe. Ruby interceptará la llamada que falla durante el tiempo de ejecución y te permitirá manejarla para que tu programa pueda recuperarse correctamente. La implementación anterior intenta acceder al hash utilizando el nombre del método como un símbolo, utilizando el nombre del método como una cadena y, finalmente, falla con el error incorporado del método incorporado de Ruby.

Para una aplicación más compleja, donde la adición de este comportamiento para todos los hashes podría romper otro código o third0party gemas, utilizar un módulo y se extienden cada instancia

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

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

y para mayor comodidad, puede incluso propagar el módulo hacia abajo a los hash anidados

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 
Cuestiones relacionadas