2012-09-06 8 views
5

Estoy usando un Struct en lugar de un Hash simple en un proyecto para proporcionar un nombre semántico a una colección de pares de valores clave. Una vez que he construido la estructura, sin embargo, necesito generar un valor hash. Estoy en Ruby 1.9.3. Ejemplo:¿Forma elegante de agregar el método to_hash (o to_h) a Struct?

MyMeaninfulName = Struct.new(:alpha, :beta, :gamma) do 
    def to_hash 
    self.members.inject({}) {|h,m| h[m] = self[m]; h} 
    end 
end 

my_var = MyMeaningfulName.new 
my_var.to_hash # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 

¿Existe una razón por la Struct no incluye un método to_hash? Parece un ajuste natural, pero tal vez haya una razón subyacente por la cual no está incluido.

En segundo lugar, hay una forma más elegante de crear un método genérico to_hash en Struct (generalmente, a través de monkeypatching, a través de un módulo o herencia).

+0

Para aclarar la segunda parte de la pregunta ... Debido a que Struct es una fábrica de clases, no estoy seguro de cómo agregar la funcionalidad to_hash (que sería fácil en cualquier clase tradicional). – GSP

+0

Si quiere aclarar, puede editar la pregunta; simplemente haga clic en el enlace ** editar ** debajo del texto de la pregunta. Por cierto, buena pregunta. +1! – Linuxios

Respuesta

0

Prueba esto:

class Struct 
    old_new = self.method(:new) 
    def self.new(*args) 
    obj = old_new.call(*args) 
    obj.class_exec do 
     def to_hash 
     self.members.inject({}) {|h,m| h[m] = self[m]; h} 
     end 
    end 
    return obj 
    end 
end 
+0

Obtengo 'variable local indefinida o método old_new' para Struct: Class' cuando intento:' clase MyClass

2

o esto:

class Struct 
    def to_hash 
    self.class.members.inject({}) {|h,m| h[m] = self[m]} 
    end 
end 

(tenga en cuenta la clase extra para llegar a los miembros)

+0

Creo que a su bloque de inyección le falta' h' como valor de retorno; esto plantea una excepción para mí. O use 'each' y mueva' h' al alcance externo. – waldrumpus

+0

Estoy dividido entre esta respuesta y Linuxios '. El suyo es más prolijo pero, para mí, más explícito sobre lo que está sucediendo exactamente. – GSP

+0

@waldrumpus - el código funciona bien para mí - qué extraño – froderik

2

No sé por qué, parece obvio . Afortunadamente, puedes usarlo como hash en muchos lugares ya que implementa operadores de corchetes.

De todos modos, esto es bastante elegante:

MyMeaningfulName = Struct.new :alpha, :beta, :gamma do 
    def to_hash 
    Hash[members.zip values] 
    end 
end 

my_var = MyMeaningfulName.new 1, 2, 3 
my_var.to_hash # => {:alpha=>1, :beta=>2, :gamma=>3} 
3

sé que la pregunta se refiere a rubí 1.9.3, pero a partir de rubí 2.0.0, Struct tiene un método to_h el que hace el trabajo.

MyMeaningfulName = Struct.new(:alpha, :beta, :gamma) 

my_var = MyMeaningfulName.new 
my_var.to_h # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 
Cuestiones relacionadas