Reputation: 89823
I'm trying to do Ruby password input with the Highline gem and since I have the user input the password twice, I'd like to eliminate the duplication on the blocks I'm passing in. For example, a simple version of what I'm doing right now is:
new_pass = ask("Enter your new password: ") { |prompt| prompt.echo = false }
verify_pass = ask("Enter again to verify: ") { |prompt| prompt.echo = false }
And what I'd like to change it to is something like this:
foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ") foo
verify_pass = ask("Enter again to verify: ") foo
Which unfortunately doesn't work. What's the correct way to do this?
Upvotes: 43
Views: 46052
Reputation: 21572
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)}
Upvotes: 4
Reputation: 12202
The code by David will work fine, but this is an easier and shorter solution:
foo = Proc.new { |prompt| prompt.echo = false }
new_pass = ask("Enter your new password: ", &foo)
verify_pass = ask("Enter again to verify: ", &foo)
You can also use an ampersand to assign a block to a variable when defining a method:
def ask(msg, &block)
puts block.inspect
end
Upvotes: 74
Reputation: 11315
Here is an example that will prefix the index with the yield method and append the index with the call method.
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
Upvotes: 2
Reputation: 4409
This is how you should do it, clean and 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)
Upvotes: 13
Reputation: 15872
I don't think the language supports a construct like this. The only way I can see to generalize this in any way is:
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) }
It doesn't really shorten the code, though it does remove some duplication--if you wanted to do more than set prompt.echo
to false
, you'd only have to add code in one place.
Upvotes: -2