Hola,
me da que esta pregunta es mas apropiada para la lista de ruby que de
rails, pero la lanzo por aquí porque supongo que a alguno os ha pasado
currando con rails.
Estoy creando un metodo de una clase dinamicamente y necesito que
reciba parámetros opcionales osea necesito definir dinamicamente un
metodo que haga esto:
def foo( args = {} )
args[:type] = value
…
end
Pues este metodo recibe un hash de opciones o un hash vacío y
necesito que esté inicializado, he probado de varias maneras y la
única manera de que funcione correctamente es
así:
define_method( :foo ) do |args|
args ||= {}
args[:type]=value
…
end
Pero claro pega un horrendo warning cuando no le paso parámetros,
aunque si funciona bien.
warning: multiple values for a block parameter (0 for 1)
¿ Ideas u otras maneras para solucionar el warning ?
Saludos
Felipe
2008/10/28 Felipe T. Armero [email protected]:
args[:type] = value
end
Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es
No es un bug, es una feature =;-)
Vamos, que es que es así, no se pueden hacer opcionales los parámetros
de un bloque (en Ruby 1.9 sí).
Pero, aunque es un poco hack, sí hay algo que puedes hacer, que es
usar el splat operator (el asterisco, vamos), que sí que se puede
hacer en 1.8:
class Hola
así lo tienes tú
define_method(:foo) do |arg|
“foo #{arg}”
end
#así lo puedes hacer
define_method(:bar) do |*args|
“bar #{args.first}”
end
end
puts Hola.new.foo(‘hey’)
imprime “foo hey”
puts Hola.new.foo
imprime “foo” y tira un warning
puts Hola.new.bar(‘tolo’)
imprime “bar tolo”
puts Hola.new.bar
imprime “bar”
Es un poco feo y pierdes el control total sobre el número de
parámetros (te pueden pasar lo que quieran, que menos el primero te
los comes) a no ser que lo hagas a mano (mirando el tamaño de args,
que es un array con todos los parámetros). Pero sigue funcionando y el
warning no aparece 
–
Sergio Gil Pérez de la Manga
e-mail > [email protected]
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras
Siempre te quedará la opción de eval, donde tienes todas las libertades
de
la metaprogramación
class A
def new_method(meth)
instance_eval <<-END
def #{meth.to_s}(args = {})
puts args[:type]
end
END
end
end
irb(main):011:0* a = A.new
=> #<A:0xb7c1d2b8>
irb(main):012:0> a.new_method(:salute)
=> nil
irb(main):013:0> a.salute
nil
=> nil
irb(main):014:0> a.salute(:type=>“good”)
good
=> nil
irb(main):015:0>
Un Saludo.
On Oct 28, 2008, at 11:36 PM, Sergio Gil Pérez de la Manga wrote:
Es un poco feo y pierdes el control total sobre el número de
parámetros (te pueden pasar lo que quieran, que menos el primero te
los comes) a no ser que lo hagas a mano (mirando el tamaño de args,
que es un array con todos los parámetros). Pero sigue funcionando y el
warning no aparece 
Estuve probando con el splat operator sin llegar a afinarlo del todo
y preferí quedarme con el warning, aparte que supuse que habría algo
mas “elegante” de solucionarlo.
Finalmente lo he solucionado
así:
define_method( :foo ) do |*args|
args=args.first
args ||= {}
raise(ArgumentError, “wrong number of arguments 3 is the
maximum.”) if args.size > 3
args.merge! :type => value
…
end
El control de parámetros lo hago comprobando a manubrio el tamaño del
hash que me llega en primer lugar y si es mas de los que necesito
salto la excepción, pues el metodo lo uso con un hash foo(:bar =>
1, :foobar => 2)
si me viene a nil lo inicializo y punto, es un hack un poco raro, pero
soluciona el asunto osea que así se queda hasta que rulemos con la
versión 1.9 
Gracias
Saludos
Felipe