2008-11-11 10 views
36

Estoy tratando de hacer la entrada de contraseña de Ruby con el Highline gem y dado que el usuario ingresa la contraseña dos veces, me gustaría eliminar la duplicación en los bloques que paso. Para ejemplo, una versión sencilla de lo que estoy haciendo en este momento es:Ruby - Paso de bloques a métodos

new_pass = ask("Enter your new password: ") { |prompt| prompt.echo = false } 
verify_pass = ask("Enter again to verify: ") { |prompt| prompt.echo = false } 

Y lo que me gustaría cambiarlo a 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 

que por desgracia no funciona . ¿Cuál es la forma correcta de hacer esto?

Respuesta

69

El código de David va a funcionar bien, pero esto es una solución más fácil y más corto:

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 utilizar un símbolo de unión para asignar un bloque a una variable en la definición de un método:

def ask(msg, &block) 
    puts block.inspect 
end 
+0

Lo intenté inicialmente (antes de hacer esta pregunta), pero cuando lo hago, Highline ignora el contenido del bloque y muere con este error: método indefinido '& 'para" inputstring ": String (NoMethodError) Donde inputstring es lo que escribí en el primer prompt. –

+0

Suena extraño. ¿Tal vez se olvidó de la coma y Ruby asumió que desea invocar el método "&" en la cadena de solicitud? Acabo de probar el mismo código con HighLine y funciona bien. –

+0

Sí, creo que estaba haciendo ask ("goo") y foo en lugar de preguntar ("goo", y foo). Eso funciona ahora. Gracias Adam! –

-2

No creo que el lenguaje sea compatible con una construcción como esta. La única manera que puedo ver generalizar esto de ninguna 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) } 

Realmente no acortar el código, aunque no eliminar algunas duplicaciones - si quería hacer algo más que ajustado a prompt.echofalse, solo tendrías que agregar código en un solo lugar.

4
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)} 
+0

Eso lo hizo! ¡Gracias por la rápida respuesta! –

13

Esta es la forma en que debe hacerlo, limpio y sencillo:

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) 
2

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 
Cuestiones relacionadas