Soy bastante nuevo para Ruby así que me disculpo si esta es una pregunta obvia.Parámetros con nombre en Ruby Structs
Me gustaría utilizar parámetros con nombre al crear una instancia de Struct, es decir, ser capaz de especificar qué elementos de Struct obtienen qué valores y el resto es nulo.
Por ejemplo, yo quiero hacer:
Movie = Struct.new :title, :length, :rating
m = Movie.new :title => 'Some Movie', :rating => 'R'
Esto no funciona.
Así que se le ocurrió la siguiente:
class MyStruct < Struct
# Override the initialize to handle hashes of named parameters
def initialize *args
if (args.length == 1 and args.first.instance_of? Hash) then
args.first.each_pair do |k, v|
if members.include? k then
self[k] = v
end
end
else
super *args
end
end
end
Movie = MyStruct.new :title, :length, :rating
m = Movie.new :title => 'Some Movie', :rating => 'R'
Esto parece funcionar bien, pero no estoy seguro de si hay una mejor manera de hacer esto, o si estoy haciendo algo bastante loco . Si alguien puede validar/desmantelar este enfoque, estaría muy agradecido.
ACTUALIZACIÓN
me encontré con este principio en 1.9.2 y funciona bien; sin embargo, habiendo probado en otras versiones de Ruby (agradecerá RVM), funciona/no funciona de la siguiente manera:
- 1.8.7: No funciona
- 1.9.1: Trabajo
- 1.9. 2: Trabajar
- JRuby (configurado para ejecutarse como 1.9.2): no funciona
JRuby es un problema para mí, ya que me gusta que sea compatible con la que, a efectos de despliegue.
otra actualización
En esta pregunta cada vez mayor laberíntica, he experimentado con las diferentes versiones de Ruby y descubrieron que en la tienda Las estructuras 1.9.x sus miembros como símbolos, pero en 1.8.7 y JRuby , que se almacenan como cadenas, así que actualizan el código a ser las siguientes (teniendo en las indicaciones ya dadas amablemente):
class MyStruct < Struct
# Override the initialize to handle hashes of named parameters
def initialize *args
return super unless (args.length == 1 and args.first.instance_of? Hash)
args.first.each_pair do |k, v|
self[k] = v if members.map {|x| x.intern}.include? k
end
end
end
Movie = MyStruct.new :title, :length, :rating
m = Movie.new :title => 'Some Movie', :rating => 'R'
Esto ahora parece funcionar para todos los sabores de Ruby que he probado.
Tu código se ve muy bien, de verdad. –
He estado buscando lo mismo: ¿hay una gema estándar que hace esto, junto con especificar qué argumentos son necesarios? –
https://github.com/chemica/solid-struct hace esto, pero no aplica los argumentos requeridos. –