manejo - Ruby: paso de bloques a métodos
manejo de clases en ruby (5)
Intento ingresar la contraseña de Ruby con la gema de Highline y dado que el usuario ingresó la contraseña dos veces, me gustaría eliminar la duplicación en los bloques que paso. Por ejemplo, una versión simple de lo que estoy haciendo en este momento es:
new_pass = ask("Enter your new password: ") { |prompt| prompt.echo = false }
verify_pass = ask("Enter again to verify: ") { |prompt| prompt.echo = false }
Y a lo que me gustaría cambiarlo es algo como esto:
foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ") foo
verify_pass = ask("Enter again to verify: ") foo
Lo cual desafortunadamente no funciona. ¿Cuál es la forma correcta de hacer esto?
No creo que el lenguaje soporte una construcción como esta. La única forma en que puedo ver para generalizar esto de alguna manera es:
def foo(prompt)
prompt.echo = false
end
new_pass = ask("Enter your new password: ") { |prompt| foo(prompt) }
verify_pass = ask("Enter again to verify: ") { |prompt| foo(prompt) }
En realidad, no acorta el código, aunque sí elimina algunas duplicaciones. Si quisiera hacer algo más que configurar prompt.echo
en false
, solo tendría que agregar el código en un lugar.
Así es como debes hacerlo, limpio y simple:
def ask(question)
yield(question)
end
proc = Proc.new { |question| puts question }
new_pass = ask("Enter your new password: ", &proc)
verify_pass = ask("Enter again to verify: ", &proc)
Aquí hay un ejemplo que prefijará el índice con el método de rendimiento y anexará el índice con el método de llamada.
class Array
def alter_each!
self.each_with_index do |n, i|
self[i] = yield(n,i)
end
end
def modify_each!(add_one = true, &block)
self.each_with_index do |n, i|
j = (add_one) ? (i + 1) : i
self[i] = block.call(n,j)
end
end
end
a = ["dog", "cat", "cow"]
a.alter_each! do |n, i|
"#{i}_#{n}"
end
a.modify_each! false do |n,i|
"#{n}_#{i}"
end
puts a
El código de David funcionará bien, pero esta es una solución más fácil y más corta:
foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ", &foo)
verify_pass = ask("Enter again to verify: ", &foo)
También puede usar un signo de & para asignar un bloque a una variable al definir un método:
def ask(msg, &block)
puts block.inspect
end
foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ") {|x| foo.call(x)}
verify_pass = ask("Enter again to verify: ") {|x| foo.call(x)}