2008-11-11 9 views
36

J'essaie de faire une entrée de mot de passe Ruby avec le Highline gem et depuis que l'utilisateur entre le mot de passe deux fois, je voudrais éliminer la duplication sur les blocs que je passe. par exemple, une version simple de ce que je fais est maintenant:Ruby - Passer des blocs à des méthodes

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

Et ce que je voudrais changer pour quelque chose comme ceci:

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

ce qui ne fonctionne malheureusement pas . Quelle est la bonne façon de faire cela?

Répondre

69

Le code de David fonctionnera bien, mais cela est un moyen plus facile et d'une solution plus courte:

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

Vous pouvez également utiliser une esperluette pour attribuer un bloc à une variable lors de la définition d'une méthode:

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

Je l'avais essayé initialement (avant de poser cette question), mais quand je fais cela, Highline ignore le contenu du bloc et meurt avec cette erreur: méthode non définie '& 'pour" inputstring ": String (NoMethodError) Où inputtring est ce que j'ai tapé à la première invite. –

+0

Cela semble étrange. Peut-être avez-vous oublié la virgule et Ruby a supposé que vous vouliez invoquer la méthode "&" sur la chaîne d'invite? Je viens d'essayer le même code avec HighLine et ça marche très bien. –

+0

Oui, je pense que je faisais demander ("goo") et foo au lieu de demander ("goo", & foo). Cela fonctionne maintenant. Merci Adam! –

-2

Je ne pense pas que le langage supporte une construction comme celle-ci. La seule façon que je peux voir de généraliser ce en aucune façon est:

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

Il ne raccourcit pas vraiment le code, mais il élimine une duplication - si vous vouliez faire bâtissons que prompt.echo à false, il suffirait d'ajouter du code au même endroit.

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

C'est fait! Merci pour la réponse rapide! –

13

Voici comment vous devriez le faire, propre et 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) 
2

Voici un exemple qui va préfixer l'index avec la méthode yield et ajouter l'index à la méthode call.

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 
Questions connexes