Pregunto por que me parece que hace falta más data para responder ¿por qué
no te sirve algo así?
def tarea_sum(nro_tarea)
> subtareas.map { |subtarea| subtarea.send("tarea%d" % nro_tarea)
> }.inject(0, &:+)
> end
>
Le agregué un poco de (ab)uso de Enumerable (map e inject), pero lo
principal es que en lugar de tener mensajes "tareaN_sum" tenés un mensjae
"tarea_sum(N)". Me huele mejor.
Sin embargo, sospecho que por algún motivo necesitás que el objeto responda
particularmente a los mensajes "tareaN_sum()", y hasta ahora ni lo que yo
propongo ni lo que propusieron Andrés o Nico cumple con eso. Pero con esta
función podrías reducir la duplicidad:
def tarea0_sum; tarea_sum(0); end
> def tarea1_sum; tarea_sum(1); end
> def tarea2_sum; tarea_sum(2); end
> def tarea3_sum; tarea_sum(3); end
> ...
>
De esta manera, en luga de copypastear 20 veces el cuerpo de la función,
sólo delegás reiteradas veces... va mejorando.
Hasta el momento lo que te propongo (1) utiliza Enumerable para hacer más
explícita la intención de lo que se quiere hacer (que es tomar las tareas N
de cada subtarea y calcular la suma); (2) reduce un poco la duplicación
factorizando el esqueleto de la función; (3) utiliza relativamente poca
"magia" (todavía no *programamos la programación*).
Pero este último punto lo podemos arreglar fácilmente (es Ruby ¿no?)... en
lugar de definir todas esas "funciones" que varían en el nombre nada más,
podemos apelar a algunas de estas alternativas:
(0..20).each do |nro_tarea|
> define_method("tarea%d_sum" % nro_tarea) { tarea_sum(nro_tarea); }
> end
>
que genera 21 métodos "tareaN_sum" (esto lo ponés donde pondrías el "def");
o sino:
def method_missing(name, *args)
super and return unless name =~ /tarea(\d+)_sum/
tarea_sum($1.to_i)
>
end
>
en este caso, method_missing es invocado cuando se le envía un mensaje a un
objeto y éste no sabe responderle (por que no tiene definido un método con
el nombre). Entonces se invoca a method_missing pasándole el nombre y los
argumentos. De esta manera podés soportar infinitos tareaN_sum... si en
cambio quisieras limitarlo a (digamos) 20, agregá la condición en la primera
línea del método (algo como unless name =~ /.../ && $1.to_i <= 20)
Si optás por el method_missing, debés tener cuidado de no redefinir otro
method_missing que se haya definido en otro lado (si la clase es tuya, no
vas a tener este problema).
PD: estoy acostumbrado a hacer cosas como "tarea#{nro_tarea}_sum" y estoy
intentando acostumbrarme a, cuando resulta más claro, usar en su lugar
"tarea%d_sum" % nro_tarea... ¿qué les parece más claro?
Saludos,
Nacho
2008/5/28 nico Santa <[EMAIL PROTECTED]>:
> def *tarea*_sum (num)
> tot = 0
> subtareas.each do |st|
> tot += eval("st.*tarea#{num}", binding , __FILE__, __LINE__)
> *
> end
> return tot
> end
>
>
>
>
> 2008/5/28 Lautaro Bonetto <[EMAIL PROTECTED]>:
>
>> Hola a todos.
>>
>> Necesito hacerles una consulta.
>> Tengo un sistema en Rails y necesito agregar a un módulos varios métodos
>> que difieren entre sí sólo en un número. Quiero tratar de evitarme tener que
>> escribirlos a todos.
>> Existe alguna forma de "programar la programación"? Traté de hacerlo con
>> EVAL, pero no me funcionó. Quizás lo hice mal.
>>
>> Ejemplo: Dos de los métodos son similares a estos:
>>
>> def *tarea0*_sum
>> tot = 0
>> subtareas.each do |st|
>> tot += st.*tarea0*
>> end
>> return tot
>> end
>>
>> def *tarea1*_sum
>> tot = 0
>> subtareas.each do |st|
>> tot += st.*tarea1*
>> end
>> return tot
>> end
>>
>> Tengo que escribir esta función "tareaXX_sum" 20 veces, y lo único que
>> varía es la parte de "tarea0" por "tarea1", "tarea2", "tarea3"... y así
>> hasta "tarea20".
>>
>> Hay alguna forma de evitarme tipear todos los métodos en el modelo?
>>
>> Desde ya muchas gracias por la ayuda.
>>
>>
>> --
>> Lautaro Bonetto
>> http://lautaro-bonetto.neurona.com
>>
>> _______________________________________________
>> Ruby mailing list
>> [email protected]
>> http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar
>>
>>
>
>
> --
> Nicolas Alejandro Santa
> Sr. Developer
>
> ELC Technologies (TM)
> Santa Barbara, CA 93102
> [EMAIL PROTECTED]
> [EMAIL PROTECTED]
> (866)863-7365 phn
> (866)893-1902 fax
>
> http://www.elctech.com
>
> +44 020 7504 1346 Tel - London Office
> +44 020 7504 1347 Fax - London Office
> _______________________________________________
> Ruby mailing list
> [email protected]
> http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar
>
>
_______________________________________________
Ruby mailing list
[email protected]
http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar